Completed Subtree Searches for Dungeon Packs

Completed the implementation of searching through dungeon subtrees to
avoid duplicates in "nearby" rooms
This commit is contained in:
SenseiKiwi 2014-03-19 13:15:30 -04:00
parent 5c44ddefe9
commit 8ebaa0f493
2 changed files with 52 additions and 26 deletions

View file

@ -138,17 +138,22 @@ public class DungeonPack
int maxSearchLength = config.allowDuplicatesInChain() ? maxRuleLength : MAX_HISTORY_LENGTH; int maxSearchLength = config.allowDuplicatesInChain() ? maxRuleLength : MAX_HISTORY_LENGTH;
ArrayList<DungeonData> history = DungeonHelper.getDungeonChainHistory(parent, this, maxSearchLength); ArrayList<DungeonData> history = DungeonHelper.getDungeonChainHistory(parent, this, maxSearchLength);
ArrayList<DungeonData> subtreeHistory; ArrayList<DungeonData> subtreeHistory = null;
/*if (config.getDuplicateSearchLevels() > 0) if (config.getDuplicateSearchLevels() > 0)
{ {
subtreeHistory = DungeonHelper.getFlatDungeonTree( // Search over (DuplicateSearchLevels - 1); zero means don't search at all,
DungeonHelper.getAncestor(parent, config.getDuplicateSearchLevels()), // one means search only up to the level of the immediate parent, and so on.
MAX_SUBTREE_LIST_SIZE); // Since we start with the parent, we need to drop the max levels by one.
NewDimData ancestor = DungeonHelper.getAncestor(parent, this, config.getDuplicateSearchLevels() - 1);
if (ancestor != null)
{
subtreeHistory = DungeonHelper.listDungeonsInTree(ancestor, this, MAX_SUBTREE_LIST_SIZE);
}
} }
else if (subtreeHistory == null)
{ {
subtreeHistory = new ArrayList<DungeonData>(); subtreeHistory = new ArrayList<DungeonData>();
}*/ }
subtreeHistory = new ArrayList<DungeonData>(); subtreeHistory = new ArrayList<DungeonData>();
return getNextDungeon(history, subtreeHistory, random); return getNextDungeon(history, subtreeHistory, random);

View file

@ -641,45 +641,66 @@ public class DungeonHelper
} }
/** /**
* Performs a breadth-first listing of all dungeons rooted at a specified dimension. Only dungeons from the same pack as the root will be included. * Performs a breadth-first listing of all dungeons rooted at a specified dimension. Only dungeons from the specified pack will be included.
* @param root - the pocket dimension that serves as the root for the dungeon tree * @param root - the pocket dimension that serves as the root for the dungeon tree
* @param pack - the pack to which any dungeons must belong in order to be listed
* @param maxSize - the maximum number of dungeons that can be listed * @param maxSize - the maximum number of dungeons that can be listed
* @return a list of the dungeons used in a given dungeon tree * @return a list of the dungeons used in a given dungeon tree
*/ */
public static ArrayList<DungeonData> listDungeonsInTree(NewDimData root, int maxSize) public static ArrayList<DungeonData> listDungeonsInTree(NewDimData root, DungeonPack pack, int maxSize)
{ {
int count = 0;
NewDimData current;
DungeonData dungeon;
ArrayList<DungeonData> dungeons = new ArrayList<DungeonData>(); ArrayList<DungeonData> dungeons = new ArrayList<DungeonData>();
Queue<NewDimData> pendingDimensions = new LinkedList<NewDimData>(); Queue<NewDimData> pendingDimensions = new LinkedList<NewDimData>();
if (root.dungeon() == null)
{
return dungeons;
}
pendingDimensions.add(root); pendingDimensions.add(root);
// Perform a breadth-first search through the dungeon graph
while (dungeons.size() < maxSize && !pendingDimensions.isEmpty()) while (dungeons.size() < maxSize && !pendingDimensions.isEmpty())
{ {
NewDimData current = pendingDimensions.remove(); current = pendingDimensions.remove();
for (NewDimData child : current.children()) dungeon = current.dungeon();
// Check that this is a dungeon, and if so, that it belongs to the pack that we want
if (dungeon != null && dungeon.dungeonType().Owner == pack)
{ {
if (child.dungeon() != null) dungeons.add(dungeon);
// Add all child dungeons for checking later
for (NewDimData child : current.children())
{ {
dungeons.add(child.dungeon());
pendingDimensions.add(child); pendingDimensions.add(child);
} }
if (dungeons.size() == maxSize)
{
break;
}
} }
} }
return dungeons; return dungeons;
} }
public static NewDimData getAncestor(NewDimData dimension, int levels) /**
* Gets the highest ancestor of a dimension with a dungeon that belongs to the specified pack.
* @param dimension - the first dimension to include in the search
* @param pack - the pack to which the ancestors must belong
* @param maxLevels - the maximum number of ancestors to check
* @return the highest ancestor that belongs to the specified pack within the specified levels, or <code>null</code> if none exists
*/
public static NewDimData getAncestor(NewDimData dimension, DungeonPack pack, int maxLevels)
{ {
// Find the ancestor of a dimension located a specified number of levels up. // Find the ancestor of a dimension located a specified number of levels up.
// If such an ancestor does not exist, return the root dimension. NewDimData parent = dimension;
return null; NewDimData current = null;
// We solve this inductively. We begin with null as the first valid ancestor,
// like a kind of virtual child dimension. Then "current" references the
// highest valid ancestor found so far and "parent" references its parent
for (int levels = 0; levels <= maxLevels; levels++)
{
if (parent == null || parent.dungeon() == null ||
parent.dungeon().dungeonType().Owner != pack)
{
break;
}
current = parent;
parent = parent.parent();
}
return current;
} }
} }