mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-10 14:26:45 +00:00
Basic world generation for entire Vault dimension
This commit is contained in:
parent
817dbcc6c4
commit
f530dafdee
@ -4,7 +4,11 @@ import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.Direction;
|
||||
import net.simon987.server.game.World;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
|
||||
public class VaultDimension {
|
||||
|
||||
@ -17,18 +21,153 @@ public class VaultDimension {
|
||||
|
||||
name = "v" + vaultDoorId + "-";
|
||||
|
||||
/*
|
||||
* Creates a group of vault worlds and pieces them together with openings.
|
||||
* For a set number of passes, a random number of vault worlds are added to each world in the
|
||||
* previous 'layer' of worlds in a random direction. Openings are added to allow movement from a
|
||||
* layer to the next, meaning that adjacent worlds are not necessarily connected, and one would
|
||||
* necessarily need to travel through 5 openings to reach the 6th layer, even when that layer is
|
||||
* less than 5 worlds away from the origin/home vault world (the one containing the exit door).
|
||||
*
|
||||
* 1. Create home world (layer 0)
|
||||
* 2. For each world in the current layer, attach a random number of new worlds
|
||||
* 3. Repeat the same step for the newly added layer
|
||||
* 4. Choose a random world from the last layer and create the vault box there (objective)
|
||||
*
|
||||
* This process is actually done in 2 passes, in the first pass, worlds are defined
|
||||
* as a set of coordinates + a list of opening directions, then they are actually generated
|
||||
*/
|
||||
|
||||
int minLayerCount = 4;
|
||||
int maxLayerCount = 6;
|
||||
int minAttachedWorld = 0;
|
||||
int maxAttachedWorld = 4; //todo cap at 4 to avoid infinite loop
|
||||
|
||||
HashMap<Integer, ArrayList<WorldBluePrint>> worldLayers = new HashMap<>();
|
||||
VaultWorldGenerator generator = new VaultWorldGenerator();
|
||||
Random random = new Random();
|
||||
|
||||
int layerCount = random.nextInt(maxLayerCount - minLayerCount) + minLayerCount;
|
||||
|
||||
ArrayList<Direction> openings = new ArrayList<>();
|
||||
openings.add(Direction.WEST);
|
||||
openings.add(Direction.SOUTH);
|
||||
openings.add(Direction.EAST);
|
||||
openings.add(Direction.NORTH);
|
||||
//1. Create home world
|
||||
WorldBluePrint homeWorld = new WorldBluePrint();
|
||||
homeWorld.coords.x = 0x7FFF;
|
||||
homeWorld.coords.y = 0x7FFF;
|
||||
worldLayers.put(0, new ArrayList<>());
|
||||
worldLayers.get(0).add(homeWorld);
|
||||
|
||||
World vWorld = generator.generateVaultWorld(0x7FFF, 0x7FFF, openings, name);
|
||||
//2. For each world in the current layer, attach a random number of new worlds
|
||||
for (int i = 1; i <= layerCount; i++) {
|
||||
|
||||
GameServer.INSTANCE.getGameUniverse().addWorld(vWorld);
|
||||
worldLayers.put(i, new ArrayList<>());
|
||||
|
||||
for (WorldBluePrint world : worldLayers.get(i - 1)) {
|
||||
|
||||
int attachedWorlds;
|
||||
if (i == 1) {
|
||||
attachedWorlds = 4; // The home world should have 4 attached worlds
|
||||
} else {
|
||||
attachedWorlds = random.nextInt(maxAttachedWorld - minAttachedWorld) + minAttachedWorld;
|
||||
}
|
||||
|
||||
for (int j = 0; j < attachedWorlds; j++) {
|
||||
|
||||
int rDirIndex = random.nextInt(4);
|
||||
|
||||
//Try 4 directions (wrap around 0..3)
|
||||
for (int attemptCount = 0; attemptCount < 4; attemptCount++) {
|
||||
Direction rDir = Direction.getDirection(rDirIndex);
|
||||
|
||||
//Don't attach a world at the same spot twice
|
||||
if (!worldExists(world.coordinatesOf(rDir), worldLayers)) {
|
||||
WorldBluePrint attachedWorld = world.attachWorld(rDir);
|
||||
worldLayers.get(i).add(attachedWorld);
|
||||
}
|
||||
rDirIndex = (rDirIndex + 1) % 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<World> lastLayerWorlds = new ArrayList<>();
|
||||
|
||||
//Generate worlds
|
||||
for (Integer key : worldLayers.keySet()) {
|
||||
|
||||
ArrayList<WorldBluePrint> layer = worldLayers.get(key);
|
||||
|
||||
for (WorldBluePrint bp : layer) {
|
||||
World vWorld = generator.generateVaultWorld(bp.coords.x, bp.coords.y, bp.openings, name);
|
||||
GameServer.INSTANCE.getGameUniverse().addWorld(vWorld);
|
||||
|
||||
if (key == layerCount - 1) {
|
||||
lastLayerWorlds.add(vWorld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//4. Choose a random world from the last layer and create the vault box there (objective)
|
||||
World objectiveWorld = lastLayerWorlds.get(random.nextInt(lastLayerWorlds.size()));
|
||||
|
||||
}
|
||||
|
||||
private boolean worldExists(Point coords, HashMap<Integer, ArrayList<WorldBluePrint>> worldLayers) {
|
||||
|
||||
//Auto-generated by IntelliJ Idea
|
||||
return worldLayers.values().stream().flatMap(Collection::stream).anyMatch(bp -> bp.coords.equals(coords));
|
||||
}
|
||||
|
||||
private class WorldBluePrint {
|
||||
|
||||
public ArrayList<Direction> openings = new ArrayList<>(4);
|
||||
|
||||
public Point coords = new Point();
|
||||
|
||||
/**
|
||||
* Update the blueprint's openings to allow traveling to the newly attached world
|
||||
*
|
||||
* @param direction direction of the world to attach (relative to this one)
|
||||
* @return The blueprint of the attached world
|
||||
*/
|
||||
public WorldBluePrint attachWorld(Direction direction) {
|
||||
|
||||
WorldBluePrint attachedWorld = new WorldBluePrint();
|
||||
|
||||
switch (direction) {
|
||||
case NORTH:
|
||||
openings.add(Direction.NORTH);
|
||||
attachedWorld.openings.add(Direction.SOUTH);
|
||||
break;
|
||||
case EAST:
|
||||
openings.add(Direction.EAST);
|
||||
attachedWorld.openings.add(Direction.WEST);
|
||||
break;
|
||||
case SOUTH:
|
||||
openings.add(Direction.SOUTH);
|
||||
attachedWorld.openings.add(Direction.NORTH);
|
||||
break;
|
||||
case WEST:
|
||||
openings.add(Direction.WEST);
|
||||
attachedWorld.openings.add(Direction.EAST);
|
||||
break;
|
||||
}
|
||||
|
||||
attachedWorld.coords.x = coords.x + direction.dX;
|
||||
attachedWorld.coords.y = coords.y + direction.dY;
|
||||
|
||||
return attachedWorld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the coordinates of a world that would be attached to this world
|
||||
*
|
||||
* @param direction direction of the attached world
|
||||
*/
|
||||
Point coordinatesOf(Direction direction) {
|
||||
|
||||
return new Point(coords.x + direction.dX, coords.y + direction.dY);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user