Added Subtree Searches for Dungeon Packs

Added a new setting to dungeon pack configs called
"DuplicateSearchLevels", which allows us to configure how many levels up
of the dungeon tree should be checked to avoid duplicating rooms used in
that subtree. In other words, it lets us avoid repeating rooms used in
neighboring branches of the dungeon. The setting has been added but it's
not fully supported yet - some additional code is needed in
DungeonHelper and it's not trivial to implement. I took a break because
doing it wrong could break dungeon selection.
This commit is contained in:
SenseiKiwi 2014-03-16 22:44:13 -04:00
parent 188ec6d68b
commit 1e5e8dcf2b
5 changed files with 67 additions and 5 deletions

View file

@ -21,6 +21,7 @@ public class DungeonPack
//FIXME: Do not release this code as an update without dealing with disowned types!
private static final int MAX_HISTORY_LENGTH = 30;
private static final int MAX_SUBTREE_LIST_SIZE = 30;
private final String name;
private final HashMap<String, DungeonType> nameToTypeMapping;
@ -136,15 +137,30 @@ public class DungeonPack
int maxSearchLength = config.allowDuplicatesInChain() ? maxRuleLength : MAX_HISTORY_LENGTH;
ArrayList<DungeonData> history = DungeonHelper.getDungeonChainHistory(dimension, this, maxSearchLength);
return getNextDungeon(history, random);
ArrayList<DungeonData> subtreeHistory;
/*if (config.getDuplicateSearchLevels() > 0)
{
subtreeHistory = DungeonHelper.getFlatDungeonTree(
DungeonHelper.getAncestor(dimension, config.getDuplicateSearchLevels()),
MAX_SUBTREE_LIST_SIZE);
}
else
{
subtreeHistory = new ArrayList<DungeonData>();
}*/
subtreeHistory = new ArrayList<DungeonData>();
return getNextDungeon(history, subtreeHistory, random);
}
private DungeonData getNextDungeon(ArrayList<DungeonData> history, Random random)
private DungeonData getNextDungeon(ArrayList<DungeonData> history, ArrayList<DungeonData> subtreeHistory, Random random)
{
//Extract the dungeon types that have been used from history and convert them into an array of IDs
int index;
int[] typeHistory = new int[history.size()];
HashSet<DungeonData> excludedDungeons = null;
boolean doExclude = !config.allowDuplicatesInChain() || !subtreeHistory.isEmpty();
for (index = 0; index < typeHistory.length; index++)
{
typeHistory[index] = history.get(index).dungeonType().ID;
@ -163,9 +179,19 @@ public class DungeonPack
if (nextType != null)
{
//Initialize the set of excluded dungeons if needed
if (excludedDungeons == null && !config.allowDuplicatesInChain())
if (excludedDungeons == null && doExclude)
{
excludedDungeons = new HashSet<DungeonData>(history);
if (config.allowDuplicatesInChain())
{
excludedDungeons = new HashSet<DungeonData>(subtreeHistory);
excludedDungeons.addAll(subtreeHistory);
}
else
{
excludedDungeons = new HashSet<DungeonData>(2 * (history.size() + subtreeHistory.size()));
excludedDungeons.addAll(history);
excludedDungeons.addAll(subtreeHistory);
}
}
//List which dungeons are allowed

View file

@ -11,6 +11,7 @@ public class DungeonPackConfig
private boolean allowPackChangeOut;
private boolean distortDoorCoordinates;
private int packWeight;
private int duplicateSearchLevels;
private ArrayList<DungeonChainRuleDefinition> rules;
public DungeonPackConfig() { }
@ -25,6 +26,7 @@ public class DungeonPackConfig
this.allowPackChangeOut = source.allowPackChangeOut;
this.distortDoorCoordinates = source.distortDoorCoordinates;
this.packWeight = source.packWeight;
this.duplicateSearchLevels = source.duplicateSearchLevels;
this.rules = (source.rules != null) ? (ArrayList<DungeonChainRuleDefinition>) source.rules.clone() : null;
}
@ -114,6 +116,16 @@ public class DungeonPackConfig
this.packWeight = packWeight;
}
public int getDuplicateSearchLevels()
{
return duplicateSearchLevels;
}
public void setDuplicateSearchLevels(int duplicateSearchLevels)
{
this.duplicateSearchLevels = duplicateSearchLevels;
}
public boolean doDistortDoorCoordinates()
{
return distortDoorCoordinates;

View file

@ -35,6 +35,8 @@ public class DungeonPackConfigReader extends BaseConfigurationProcessor<DungeonP
private final int DEFAULT_PRODUCT_WEIGHT = 100;
private final int MAX_DUNGEON_PACK_WEIGHT = 10000;
private final int MIN_DUNGEON_PACK_WEIGHT = 1;
private final int MAX_DUPLICATE_SEARCH_LEVELS = 5;
private final int MIN_DUPLICATE_SEARCH_LEVELS = 0;
private final int DEFAULT_DUNGEON_PACK_WEIGHT = 100;
private final int MAX_CONDITION_LENGTH = 20;
private final int MAX_PRODUCT_COUNT = MAX_CONDITION_LENGTH;
@ -80,6 +82,7 @@ public class DungeonPackConfigReader extends BaseConfigurationProcessor<DungeonP
config.setAllowPackChangeOut(true);
config.setDistortDoorCoordinates(false);
config.setPackWeight(DEFAULT_DUNGEON_PACK_WEIGHT);
config.setDuplicateSearchLevels(MIN_DUPLICATE_SEARCH_LEVELS);
//Read the settings section
if (findSection("Settings", reader))
@ -273,6 +276,18 @@ public class DungeonPackConfigReader extends BaseConfigurationProcessor<DungeonP
valid = false;
}
}
else if (name.equalsIgnoreCase("DuplicateSearchLevels"))
{
int levels = Integer.parseInt(value);
if (levels >= MIN_DUPLICATE_SEARCH_LEVELS && levels <= MAX_DUPLICATE_SEARCH_LEVELS)
{
config.setDuplicateSearchLevels(levels);
}
else
{
valid = false;
}
}
else
{
valid = false;

View file

@ -615,7 +615,7 @@ public class DungeonHelper
{
throw new IllegalArgumentException("dimension cannot be null.");
}
if(dimension.parent()==null)
if (dimension.parent() == null)
{
return new ArrayList<DungeonData>();
}
@ -664,4 +664,11 @@ public class DungeonHelper
}
return dungeons;
}
public static NewDimData getAncestor(NewDimData dimension, int levels)
{
// Find the ancestor of a dimension located a specified number of levels up.
// If such an ancestor does not exist, return the root dimension.
return null;
}
}

View file

@ -16,6 +16,8 @@ DistortDoorCoordinates = true
## Prevent this pack from being selected for transitioning in once we've transitioned out
AllowPackChangeIn = false
DuplicateSearchLevels = 1
Rules:
Exit -> DeadEnd Exit