Now with file-based level grammar.

This commit is contained in:
Woody Folsom
2012-03-18 10:56:25 -04:00
parent b431d5efeb
commit d6516388ad
8 changed files with 234 additions and 9 deletions

View File

@@ -1,12 +1,128 @@
package dk.itu.mario.level.grammar;
import dk.itu.mario.level.LevelArchetype;
import dk.itu.mario.level.LevelComponent;
import dk.itu.mario.level.PlayerProfile;
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(PlayerProfile playerProfile, LevelArchetype archetype) {
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);
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);