A boring overland world was generated from a grammar!

This commit is contained in:
Woody Folsom
2012-03-17 14:15:38 -04:00
parent 8bedf88fd3
commit 653c7fc3df
7 changed files with 231 additions and 18 deletions

View File

@@ -7,6 +7,8 @@ import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import dk.itu.mario.level.LevelComponent.TYPE;
public class LevelGrammar {
private Variable start;
@@ -45,6 +47,24 @@ public class LevelGrammar {
return generateRandom(new Random().nextLong());
}
//TODO: refactor to recursively add children to the current node based on production rule
public LevelParseTree generateRandomTree(long randomSeed, int width) {
System.out.println("Generating random level parameters using seed: "
+ randomSeed);
List<Variable> startRuleRHS = getRule(getStart()).getRHS();
ParseNode rootNode = new ParseNode(TYPE.FLAT,1.0);
LevelParseTree parseTree = new LevelParseTree(rootNode, 0, width);
for (Variable var : startRuleRHS) {
if (var.isTerminal()) {
rootNode.addChild(new ParseNode(TYPE.FLAT,0.5));
}
}
return parseTree;
}
public ProductionRule getRule(Variable var) {
return ruleMap.get(var);
}

View File

@@ -0,0 +1,52 @@
package dk.itu.mario.level.grammar;
import java.util.ArrayList;
import java.util.List;
import dk.itu.mario.level.LevelComponent;
public class LevelParseTree {
private ParseNode root;
private int start;
private int width;
public LevelParseTree(ParseNode root, int start, int width) {
this.root = root;
this.start = start;
this.width = width;
}
public List<LevelComponent> getLevelTemplate() {
List<LevelComponent> levelCompList = new ArrayList<LevelComponent>();
getComponents(root,start,width, levelCompList);
return levelCompList;
}
/**
* Enumerate the leaf nodes (level components) in depth-first order.
* @param node
* @param start
* @param end
*/
private void getComponents(ParseNode node, int start, int end, List<LevelComponent> levelCompList) {
int numChildren = node.getNumChildren();
if (numChildren == 0) {
LevelComponent.TYPE lcType = node.getType();
levelCompList.add(new LevelComponent(lcType, start, end));
} else {
int width = end - start;
int childOffset = 0;
for (int childIndex = 0; childIndex < numChildren; childIndex++) {
ParseNode childNode = node.getChild(childIndex);
int childStart = start + childOffset;
int childWidth = (int)(width * childNode.getPercentLength());
if (childIndex > 0) {
getComponents(childNode,childStart+1,childStart + childWidth,levelCompList);
} else { // don't offset by 1 if this is the first child component.
getComponents(childNode,childStart,childStart + childWidth,levelCompList);
}
childOffset += childWidth;
}
}
}
}

View File

@@ -0,0 +1,62 @@
package dk.itu.mario.level.grammar;
import java.util.ArrayList;
import java.util.List;
import dk.itu.mario.level.LevelComponent;
public class ParseNode {
private LevelComponent.TYPE levelCompType;
private double percentLength;
private List<ParseNode> children = new ArrayList<ParseNode>();
public ParseNode(LevelComponent.TYPE levelCompType, double percentLength) {
this.levelCompType = levelCompType;
this.percentLength = percentLength;
}
public void addChild(ParseNode child) {
children.add(child);
}
public LevelComponent.TYPE getType() {
return levelCompType;
}
public ParseNode getChild(int index) {
return children.get(index);
}
public int getNumChildren() {
return children.size();
}
public double getPercentLength() {
return percentLength;
}
public void setChildLengthRatios(double... childPercentLengths) {
double sumLength = 0.0;
for (double cpl : childPercentLengths) {
sumLength += cpl;
}
if (childPercentLengths.length != children.size()) {
throw new IllegalArgumentException(
"Error - number of requested child percent lengths to set does not match the number of children: "
+ childPercentLengths.length
+ " != "
+ children.size());
}
if (Math.abs(sumLength - 1.0) > 0.01) {
throw new IllegalArgumentException(
"Error - requested child percent lengths do not sum to 100% within an error of 1%.");
}
for (int i = 0; i < childPercentLengths.length; i++) {
children.get(i).setPercentLength(childPercentLengths[i]);
}
}
public void setPercentLength(double percentLength) {
this.percentLength = percentLength;
}
}