123 lines
3.2 KiB
Java
123 lines
3.2 KiB
Java
package dk.itu.mario.level.grammar;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
import java.util.TreeSet;
|
|
|
|
import dk.itu.mario.level.LevelComponent;
|
|
import dk.itu.mario.level.LevelComponent.TYPE;
|
|
|
|
public class LevelGrammar {
|
|
private Variable start;
|
|
private Map<Variable, ProductionRule> ruleMap = new HashMap<Variable, ProductionRule>();
|
|
private Set<Variable> variables = new TreeSet<Variable>();
|
|
|
|
public void addVariable(Variable var) {
|
|
if (variables.contains(var)) {
|
|
throw new IllegalArgumentException(
|
|
"Grammar already contains variable: " + var);
|
|
}
|
|
variables.add(var);
|
|
}
|
|
|
|
public void addProductionRule(ProductionRule rule) {
|
|
if (ruleMap.containsKey(rule.getLHS())) {
|
|
throw new IllegalArgumentException(
|
|
"Grammar already contains rule with LHS: " + rule.getLHS());
|
|
}
|
|
ruleMap.put(rule.getLHS(), rule);
|
|
}
|
|
|
|
public LevelParseTree generateRandomTree(long randomSeed, int width) {
|
|
System.out.println("Generating random level parameters using seed: "
|
|
+ randomSeed);
|
|
Variable startRuleLHS = getStart();
|
|
|
|
ParseNode rootNode = new ParseNode(startRuleLHS.getType(), 1.0);
|
|
generateRecursive(rootNode, getRule(startRuleLHS).getRHS(), 1.0);
|
|
LevelParseTree parseTree = new LevelParseTree(rootNode, 0, width);
|
|
|
|
return parseTree;
|
|
}
|
|
|
|
private ParseNode generateRecursive(ParseNode parseNode, Clause clause,
|
|
double relativeWidth) {
|
|
if (clause.isVariable()) {
|
|
if (clause.isTerminal()) {
|
|
parseNode.addChild(new ParseNode(((Variable) clause).getType(),
|
|
relativeWidth));
|
|
} else {
|
|
generateRecursive(parseNode, getRule((Variable) clause)
|
|
.getRHS(), relativeWidth);
|
|
}
|
|
} else {
|
|
if (clause.isChoice()) {
|
|
generateRecursive(parseNode, clause.makeRandomChoice(),
|
|
relativeWidth);
|
|
} else {
|
|
int numSubClauses = clause.getNumSubClauses();
|
|
for (int i = 0; i < numSubClauses; i++) {
|
|
generateRecursive(parseNode, clause.getSubClause(i),
|
|
relativeWidth / numSubClauses);
|
|
}
|
|
}
|
|
}
|
|
return parseNode;
|
|
}
|
|
|
|
public Variable getVariable(String varName) {
|
|
for (Variable var : variables) {
|
|
if (varName.equals(var.getValue())) {
|
|
return var;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public ProductionRule getRule(Variable var) {
|
|
return ruleMap.get(var);
|
|
}
|
|
|
|
public Variable getStart() {
|
|
return start;
|
|
}
|
|
|
|
public void setStart(String startVar) {
|
|
for (Variable var : variables) {
|
|
if (startVar.equals(var.getValue())) {
|
|
start = var;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setStart(Variable start) {
|
|
this.start = start;
|
|
}
|
|
|
|
public String toString() {
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append("Variables:\n");
|
|
for (Variable var : variables) {
|
|
sb.append("VAR ");
|
|
sb.append(var.getValue());
|
|
sb.append(" = ");
|
|
sb.append(var.getType());
|
|
sb.append("\n");
|
|
}
|
|
sb.append("\n");
|
|
for (Entry<Variable,ProductionRule> entry : ruleMap.entrySet()) {
|
|
//could as easily have used LHS instead of getKey().getValue()
|
|
sb.append("RULE " + entry.getKey().getValue() + " -> " + entry.getValue().getRHS());
|
|
sb.append("\n");
|
|
}
|
|
sb.append("\n");
|
|
sb.append("START = " + start.getValue());
|
|
return sb.toString();
|
|
}
|
|
}
|