package org.mafagafogigante.dungeon.game;
import org.mafagafogigante.dungeon.game.LocationPreset.Type;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
/**
* The world generator. This class should be instantiated by a World object.
*/
class WorldGenerator implements Serializable {
private static final int DEFAULT_CHUNK_SIDE = 5;
private final World world;
private final RiverGenerator riverGenerator;
private final DungeonDistributor dungeonDistributor = new DungeonDistributor();
private final DungeonCreator dungeonCreator = new DungeonCreator(dungeonDistributor);
private final int chunkSide;
WorldGenerator(World world) {
this.world = world;
this.riverGenerator = new RiverGenerator();
this.chunkSide = WorldGenerator.DEFAULT_CHUNK_SIDE;
}
/**
* Retrieves a random LocationPreset whose type is "Land".
*
* @return a LocationPreset
*/
private static LocationPreset getRandomLandLocationPreset() {
LocationPresetStore locationPresetStore = LocationPresetStore.getDefaultLocationPresetStore();
return Random.select(locationPresetStore.getLocationPresetsByType(Type.LAND));
}
private Location createRandomRiverLocation(@NotNull final Point point) {
LocationPresetStore locationPresetStore = LocationPresetStore.getDefaultLocationPresetStore();
return new Location(Random.select(locationPresetStore.getLocationPresetsByType(Type.RIVER)), world, point);
}
private Location createRandomBridgeLocation(@NotNull final Point point) {
LocationPresetStore locationPresetStore = LocationPresetStore.getDefaultLocationPresetStore();
return new Location(Random.select(locationPresetStore.getLocationPresetsByType(Type.BRIDGE)), world, point);
}
public void expand(Point point) {
riverGenerator.expand(point, chunkSide);
Point currentPoint;
LocationPreset currentLocationPreset = null;
int remainingLocationsOfCurrentPreset = 0;
int pX = point.getX();
int pY = point.getY();
// Get the closest smaller chunkSide multiple of x and y.
// For instance, if chunkSide == 5, x == -2 and y == 1, then it makes xStart == -5 and yStart == 0.
int xStart = pX < 0 ? chunkSide * (((pX + 1) / chunkSide) - 1) : chunkSide * (pX / chunkSide);
int yStart = pY < 0 ? chunkSide * (((pY + 1) / chunkSide) - 1) : chunkSide * (pY / chunkSide);
for (int x = xStart; x < xStart + chunkSide; x++) {
for (int y = yStart; y < yStart + chunkSide; y++) {
currentPoint = new Point(x, y, 0);
if (!world.alreadyHasLocationAt(currentPoint)) {
if (riverGenerator.isRiver(currentPoint)) {
world.addLocation(createRandomRiverLocation(currentPoint), currentPoint);
} else if (riverGenerator.isBridge(currentPoint)) {
world.addLocation(createRandomBridgeLocation(currentPoint), currentPoint);
} else if (dungeonDistributor.rollForDungeon(currentPoint)) {
dungeonCreator.createDungeon(world, currentPoint);
} else {
if (currentLocationPreset == null || remainingLocationsOfCurrentPreset == 0) {
currentLocationPreset = getRandomLandLocationPreset();
remainingLocationsOfCurrentPreset = currentLocationPreset.getBlobSize();
}
world.addLocation(new Location(currentLocationPreset, world, currentPoint), currentPoint);
remainingLocationsOfCurrentPreset--;
}
}
}
}
}
}