190 lines
5.9 KiB
Java
190 lines
5.9 KiB
Java
package dk.itu.mario.level.grammar;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import dk.itu.mario.level.LevelComponent;
|
|
|
|
public class LevelGrammarFactory {
|
|
public static LevelGrammar createGrammar(File grammarFile) throws FileNotFoundException, IOException {
|
|
FileInputStream fis = new FileInputStream(grammarFile);
|
|
LevelGrammar levelGrammar = new LevelGrammar();
|
|
try {
|
|
InputStreamReader reader = new InputStreamReader(fis);
|
|
BufferedReader buf = new BufferedReader(reader);
|
|
String line;
|
|
while ((line = buf.readLine()) != null) {
|
|
line = line.trim(); // trim off newline/whitespace
|
|
if (line.length() == 0 || line.startsWith("#")) {
|
|
continue;
|
|
}
|
|
//System.out.println("Read: " + line);
|
|
//split on whitespace
|
|
String[] fields;
|
|
if (line.startsWith("VAR")) {
|
|
fields = line.split("\\s");
|
|
if ("=".equals(fields[2]) && fields.length == 4) {
|
|
levelGrammar.addVariable(new Variable(fields[1],LevelComponent.TYPE.valueOf(fields[3])));
|
|
} else {
|
|
throw new RuntimeException("Invalid VAR syntax: " + line);
|
|
}
|
|
} else if (line.startsWith("RULE")) {
|
|
fields = line.split("->");
|
|
String ruleName = fields[0].split("\\s")[1];
|
|
//System.out.println("Rule name: " + ruleName);
|
|
Variable lhs = levelGrammar.getVariable(ruleName);
|
|
if (lhs == null) {
|
|
throw new RuntimeException("LHS variable not found: " + ruleName);
|
|
}
|
|
Clause rhs = getClause(fields[1].trim(),levelGrammar);
|
|
levelGrammar.addProductionRule(new ProductionRule(lhs,rhs));
|
|
} else if (line.startsWith("START")) {
|
|
fields = line.split("\\s");
|
|
if ("=".equals(fields[1]) && fields.length == 3) {
|
|
levelGrammar.setStart(fields[2]);
|
|
} else {
|
|
throw new RuntimeException("Invalid START syntax: " + line);
|
|
}
|
|
} else {
|
|
throw new RuntimeException("Unable to parse grammar file " + grammarFile.getName() + " due to invalid line: " + line);
|
|
}
|
|
}
|
|
return levelGrammar;
|
|
} finally {
|
|
fis.close();
|
|
}
|
|
}
|
|
|
|
private static Clause getClause(String clause, LevelGrammar grammar) {
|
|
if (!clause.contains("|") && !clause.contains("+")) {
|
|
return grammar.getVariable(clause);
|
|
}
|
|
int lBraceIndex = clause.indexOf("{");
|
|
boolean isOrClause = false;
|
|
int rBraceIndex = 0;
|
|
|
|
double[] chances = {};
|
|
|
|
if (lBraceIndex != -1) {
|
|
isOrClause = true;
|
|
rBraceIndex = clause.indexOf("}");
|
|
//System.out.println("Read OR-clause probabilities from: " + lBraceIndex + " to " + rBraceIndex);
|
|
String[] doubleFields = clause.substring(lBraceIndex+1,rBraceIndex).split(",");
|
|
chances = new double[doubleFields.length];
|
|
for (int i = 0; i < doubleFields.length; i++) {
|
|
chances[i] = Double.valueOf(doubleFields[i]);
|
|
}
|
|
}
|
|
|
|
String remainder = clause.substring(rBraceIndex);
|
|
if (remainder.startsWith("}, ")) {
|
|
remainder = remainder.substring(3);
|
|
}
|
|
List<String> rhsClauseStrings = new ArrayList<String>();
|
|
if (remainder.contains("(")) {
|
|
int nextLeftIndex = -1;
|
|
do {
|
|
nextLeftIndex = remainder.indexOf("(", nextLeftIndex+1);
|
|
if (nextLeftIndex != -1) {
|
|
int nextRightIndex = remainder.indexOf(")", nextLeftIndex+1);
|
|
if (nextRightIndex == -1) {
|
|
throw new RuntimeException("Unmatched left '(' in clause");
|
|
}
|
|
rhsClauseStrings.add(remainder.substring(nextLeftIndex+1,nextRightIndex));
|
|
nextLeftIndex = nextRightIndex;
|
|
}
|
|
} while (nextLeftIndex != -1);
|
|
} else {
|
|
isOrClause = remainder.contains("|");
|
|
if (isOrClause) {
|
|
for (String subclause : remainder.split("\\|")) {
|
|
rhsClauseStrings.add(subclause.trim());
|
|
}
|
|
} else {
|
|
for (String subclause : remainder.split("\\+")) {
|
|
rhsClauseStrings.add(subclause.trim());
|
|
}
|
|
}
|
|
}
|
|
|
|
List<Clause> rhsClauses = new ArrayList<Clause>();
|
|
|
|
for (String subclause : rhsClauseStrings) {
|
|
rhsClauses.add(getClause(subclause,grammar));
|
|
}
|
|
|
|
if (isOrClause) {
|
|
return new OrClause(chances, rhsClauses);
|
|
} else {
|
|
return new AndClause(rhsClauses);
|
|
}
|
|
}
|
|
public static LevelGrammar createGrammar() {
|
|
LevelGrammar grammar = new LevelGrammar();
|
|
|
|
Variable v_START = new Variable("S", LevelComponent.TYPE.LEVEL);
|
|
Variable v_LAND_SEGMENT = new Variable("HALF_LVL", LevelComponent.TYPE.LEVEL_SEGMENT);
|
|
Variable v_LO_HI = new Variable("LO_HI", LevelComponent.TYPE.LO_HI);
|
|
Variable v_HI_LO = new Variable("HI_LO", LevelComponent.TYPE.HI_LO);
|
|
Variable v_LO_PATH = new Variable("LO_PATH", LevelComponent.TYPE.LO_PATH);
|
|
Variable v_HI_PATH = new Variable("HI_PATH", LevelComponent.TYPE.HI_PATH);
|
|
Variable v_lo_path = new Variable("lo_path", LevelComponent.TYPE.FLAT_LO);
|
|
Variable v_hi_path = new Variable("hi_path", LevelComponent.TYPE.FLAT_HI);
|
|
|
|
grammar.addVariable(v_START);
|
|
grammar.addVariable(v_LAND_SEGMENT);
|
|
grammar.addVariable(v_LO_HI);
|
|
grammar.addVariable(v_HI_LO);
|
|
grammar.addVariable(v_LO_PATH);
|
|
grammar.addVariable(v_HI_PATH);
|
|
|
|
grammar.addProductionRule(new ProductionRule(v_START,v_LAND_SEGMENT,v_LAND_SEGMENT));
|
|
|
|
grammar.addProductionRule(
|
|
new ProductionRule(v_LAND_SEGMENT,
|
|
new OrClause( new double[] {0.25,0.65,0.10},
|
|
new AndClause(v_LO_HI,v_HI_LO),
|
|
v_LO_PATH,
|
|
new AndClause(v_LAND_SEGMENT,v_LAND_SEGMENT)
|
|
)
|
|
)
|
|
);
|
|
|
|
grammar.addProductionRule(
|
|
new ProductionRule(v_LO_HI, v_LO_PATH, v_HI_PATH)
|
|
);
|
|
|
|
grammar.addProductionRule(
|
|
new ProductionRule(v_HI_LO, v_HI_PATH, v_LO_PATH)
|
|
);
|
|
|
|
grammar.addProductionRule(
|
|
new ProductionRule(v_HI_PATH,
|
|
new OrClause( new double[] {0.25,0.75},
|
|
new AndClause(v_HI_PATH,v_HI_PATH),
|
|
v_hi_path
|
|
)
|
|
)
|
|
);
|
|
|
|
grammar.addProductionRule(
|
|
new ProductionRule(v_LO_PATH,
|
|
new OrClause( new double[] {0.25,0.75},
|
|
new AndClause(v_LO_PATH,v_LO_PATH),
|
|
v_lo_path
|
|
)
|
|
)
|
|
);
|
|
|
|
grammar.setStart(v_START);
|
|
|
|
return grammar;
|
|
}
|
|
}
|