Partial Dungeon Pack and Configurable Dungeon Chain Implementation #67

Merged
SenseiKiwi merged 9 commits from DungeonPacks into master 2013-08-18 15:24:50 +00:00
7 changed files with 180 additions and 28 deletions
Showing only changes of commit f372b9ccb5 - Show all commits

View File

@@ -43,12 +43,15 @@ public class SchematicLoader
if (dimList.get(destDimID).dungeonGenerator == null) if (dimList.get(destDimID).dungeonGenerator == null)
{ {
//The following initialization code is based on code from ChunkProviderGenerate. //The following initialization code is based on code from ChunkProviderGenerate.
//It makes our generation depend on the world seed. //It makes our generation depend on the world seed. We have an additional seed here
//to prevent correlations between the selected dungeons and the locations of gateways.
//TODO: We should centralize RNG initialization and world-seed modifiers for each specific application.
Random random = new Random(world.getSeed()); final long localSeed = world.getSeed() ^ 0x2F50DB9B4A8057E4L;
long factorA = random.nextLong() / 2L * 2L + 1L; final Random random = new Random();
long factorB = random.nextLong() / 2L * 2L + 1L; final long factorA = random.nextLong() / 2L * 2L + 1L;
random.setSeed((link.destXCoord >> 4) * factorA + (link.destZCoord >> 4) * factorB ^ world.getSeed()); final long factorB = random.nextLong() / 2L * 2L + 1L;
random.setSeed((link.destXCoord >> 4) * factorA + (link.destZCoord >> 4) * factorB ^ localSeed);
dungeonHelper.generateDungeonLink(link, dungeonHelper.RuinsPack, random); dungeonHelper.generateDungeonLink(link, dungeonHelper.RuinsPack, random);
} }

View File

@@ -15,12 +15,13 @@ public class DungeonChainRule
ArrayList<String> conditionNames = source.getCondition(); ArrayList<String> conditionNames = source.getCondition();
ArrayList<WeightedContainer<String>> productNames = source.getProducts(); ArrayList<WeightedContainer<String>> productNames = source.getProducts();
//Obtain the IDs of dungeon types in reverse order. Reverse order makes comparing against chain histories easy.
condition = new int[conditionNames.size()]; condition = new int[conditionNames.size()];
for (int k = 0; k < condition.length; k++) for (int src = 0, dst = condition.length - 1; src < condition.length; src++, dst--)
{ {
condition[k] = nameToTypeMapping.get(conditionNames.get(k)).ID; condition[dst] = nameToTypeMapping.get(conditionNames.get(src)).ID;
} }
products = new ArrayList<WeightedContainer<DungeonType>>(); products = new ArrayList<WeightedContainer<DungeonType>>(productNames.size());
for (WeightedContainer<String> product : productNames) for (WeightedContainer<String> product : productNames)
{ {
products.add(new WeightedContainer<DungeonType>(nameToTypeMapping.get(product.getData()), product.itemWeight )); products.add(new WeightedContainer<DungeonType>(nameToTypeMapping.get(product.getData()), product.itemWeight ));

View File

@@ -166,7 +166,7 @@ public class DungeonPack
//List which dungeons are allowed //List which dungeons are allowed
ArrayList<DungeonGenerator> candidates; ArrayList<DungeonGenerator> candidates;
ArrayList<DungeonGenerator> group = groupedDungeons.get(nextType.ID); ArrayList<DungeonGenerator> group = groupedDungeons.get(nextType.ID);
if (excludedDungeons != null) if (excludedDungeons != null && !excludedDungeons.isEmpty())
{ {
candidates = new ArrayList<DungeonGenerator>(group.size()); candidates = new ArrayList<DungeonGenerator>(group.size());
for (DungeonGenerator dungeon : group) for (DungeonGenerator dungeon : group)

View File

@@ -9,7 +9,9 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue;
import java.util.Random; import java.util.Random;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -423,32 +425,72 @@ public class DungeonHelper
//manipulate the output of this function by setting up links to mislead our algorithm or by removing links. //manipulate the output of this function by setting up links to mislead our algorithm or by removing links.
//Dimensions MUST have built-in records of their parent dimensions in the future. ~SenseiKiwi //Dimensions MUST have built-in records of their parent dimensions in the future. ~SenseiKiwi
dimHelper helper = dimHelper.instance;
ArrayList<DungeonGenerator> history = new ArrayList<DungeonGenerator>(); ArrayList<DungeonGenerator> history = new ArrayList<DungeonGenerator>();
DimData tailDim = helper.getDimData(helper.getLinkDataFromCoords(dimData.exitDimLink.destXCoord, dimData.exitDimLink.destYCoord, dimData.exitDimLink.destZCoord, dimData.exitDimLink.destDimID).destDimID); DimData tailDim = dimData;
boolean found = true;
for (int count = 0; count < maxSize; count++) if (dimData.dungeonGenerator == null || dimData.dungeonGenerator.getDungeonType().Owner != pack || maxSize < 1)
{ {
if (tailDim.dungeonGenerator == null || tailDim.dungeonGenerator.getDungeonType().Owner != pack) //The initial dimension is already outside our pack. Return an empty list.
{ return history;
//We've reached a dimension that doesn't belong to our pack. Stop the search here.
break;
} }
history.add(dimData.dungeonGenerator);
history.add(tailDim.dungeonGenerator); for (int count = 1; count < maxSize && found; count++)
if (count + 1 < maxSize)
{ {
found = false;
for (LinkData link : tailDim.getLinksInDim()) for (LinkData link : tailDim.getLinksInDim())
{ {
DimData nextDim = dimHelper.instance.getDimData(link.destDimID); DimData neighbor = dimHelper.instance.getDimData(link.destDimID);
if (helper.getDimDepth(link.destDimID) == tailDim.depth + 1) if (neighbor.depth == tailDim.depth - 1 && neighbor.dungeonGenerator != null &&
neighbor.dungeonGenerator.getDungeonType().Owner == pack)
{ {
tailDim = nextDim; tailDim = neighbor;
history.add(tailDim.dungeonGenerator);
found = true;
break; break;
} }
} }
} }
}
return history; return history;
} }
public static ArrayList<DungeonGenerator> getFlatDungeonTree(DimData dimData, int maxSize)
{
//TODO: I've improved this code for the time being. However, searching across links is a flawed approach. A player could
//manipulate the output of this function by setting up links to mislead our algorithm or by removing links.
//Dimensions MUST have built-in records of their parent dimensions in the future. ~SenseiKiwi
dimHelper helper = dimHelper.instance;
ArrayList<DungeonGenerator> dungeons = new ArrayList<DungeonGenerator>();
DimData root = helper.getDimData(helper.getLinkDataFromCoords(dimData.exitDimLink.destXCoord, dimData.exitDimLink.destYCoord, dimData.exitDimLink.destZCoord, dimData.exitDimLink.destDimID).destDimID);
HashSet<DimData> checked = new HashSet<DimData>();
Queue<DimData> pendingDimensions = new LinkedList<DimData>();
if (root.dungeonGenerator == null)
{
return dungeons;
}
pendingDimensions.add(root);
checked.add(root);
while (dungeons.size() < maxSize && !pendingDimensions.isEmpty())
{
DimData current = pendingDimensions.remove();
for (LinkData link : current.getLinksInDim())
{
DimData child = helper.getDimData(link.destDimID);
if (child.depth == current.depth + 1 && child.dungeonGenerator != null && checked.add(child))
{
dungeons.add(child.dungeonGenerator);
pendingDimensions.add(child);
}
if (dungeons.size() == maxSize)
{
break;
}
}
}
return dungeons;
}
} }

View File

@@ -0,0 +1,52 @@
package StevenDimDoors.mod_pocketDim.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public abstract class BaseConfigurationProcessor<T>
{
public BaseConfigurationProcessor() { }
public boolean canRead()
{
return true;
}
public boolean canWrite()
{
return true;
}
public T readFromFile(String path) throws FileNotFoundException, ConfigurationProcessingException
{
return readFromFile(new File(path));
}
public T readFromFile(File file) throws FileNotFoundException, ConfigurationProcessingException
{
return readFromStream(new FileInputStream(file));
}
public T readFromResource(String resourcePath) throws ConfigurationProcessingException
{
return readFromStream(this.getClass().getResourceAsStream(resourcePath));
}
public abstract T readFromStream(InputStream inputStream) throws ConfigurationProcessingException;
public void writeToFile(File file, T data) throws FileNotFoundException, ConfigurationProcessingException
{
writeToStream(new FileOutputStream(file), data);
}
public void writeToFile(String path, T data) throws FileNotFoundException, ConfigurationProcessingException
{
writeToFile(new File(path), data);
}
public abstract void writeToStream(OutputStream outputStream, T data) throws ConfigurationProcessingException;
}

View File

@@ -0,0 +1,21 @@
package StevenDimDoors.mod_pocketDim.util;
public class ConfigurationProcessingException extends Exception
{
private static final long serialVersionUID = -4525298050874891911L;
public ConfigurationProcessingException()
{
super();
}
public ConfigurationProcessingException(String message)
{
super(message);
}
public ConfigurationProcessingException(String message, Throwable cause)
{
super(message, cause);
}
}

View File

@@ -0,0 +1,33 @@
Version 1
Types:
Hub
Trap
SimpleHall
ComplexHall
Exit
DeadEnd
Maze
Settings:
AllowRepetitionsInBranch = false
AllowPackChangeOut = true
AllowPackChangeIn = true
PackWeight = 100
Rules:
Exit -> DeadEnd Exit
DeadEnd -> DeadEnd Exit
? ? ? ? ? ? ? ? -> Trap#20 SimpleHall#40 ComplexHall#10 Exit#20 DeadEnd#10
? ? ? ? -> Trap#18 SimpleHall#40 ComplexHall#10 Exit#18 DeadEnd#10 Hub#4
? ? ? -> ComplexHall Hub Trap SimpleHall Maze
? ? -> ComplexHall Hub Trap SimpleHall Maze
? -> ComplexHall#40 Hub#30 Trap#10 SimpleHall#10 Maze#10
-> ComplexHall#40 Hub#30 Trap#10 SimpleHall#10 Maze#10