Functional context-free grammar! Worked first time! Well... almost.
This commit is contained in:
@@ -21,7 +21,8 @@ public class PCGLevel extends Level {
|
|||||||
public static int COIN_REWARD = 1;
|
public static int COIN_REWARD = 1;
|
||||||
public static int POWERUP_REWARD = 2;
|
public static int POWERUP_REWARD = 2;
|
||||||
|
|
||||||
public static boolean TESTING = true;
|
// disable TESTING - enable grammar-based level generation
|
||||||
|
public static boolean TESTING = false;
|
||||||
public static long lastSeed;
|
public static long lastSeed;
|
||||||
private static Random levelSeedRandom = new Random();
|
private static Random levelSeedRandom = new Random();
|
||||||
|
|
||||||
@@ -181,38 +182,32 @@ public class PCGLevel extends Level {
|
|||||||
for (LevelComponent lcomp : levelTemplate) {
|
for (LevelComponent lcomp : levelTemplate) {
|
||||||
LevelComponent.TYPE lctype = lcomp.getType();
|
LevelComponent.TYPE lctype = lcomp.getType();
|
||||||
System.out.println("Building for: " + lcomp);
|
System.out.println("Building for: " + lcomp);
|
||||||
switch (lctype) {
|
while (length < Math.min(width - 64, lcomp.getEnd())) {
|
||||||
case FLAT_LO:
|
switch (lctype) {
|
||||||
case FLAT_HI:
|
case FLAT_LO:
|
||||||
length += buildStraight(length, lcomp.getEnd(), true);
|
case FLAT_HI:
|
||||||
break;
|
length += buildStraight(length, lcomp.getEnd(), true);
|
||||||
case PIPE_JUMP:
|
break;
|
||||||
length += buildPipeJump(length, width - 64 - length);
|
case PIPE_JUMP:
|
||||||
break;
|
length += buildPipeJump(length, width - 64 - length);
|
||||||
case PLATFORM_JUMP:
|
break;
|
||||||
length += buildPlatformJump(length, width - 64 - length);
|
case PLATFORM_JUMP:
|
||||||
break;
|
length += buildPlatformJump(length, width - 64 - length);
|
||||||
case MAZE:
|
break;
|
||||||
length += buildMaze(length, width - 64 - length);
|
case MAZE:
|
||||||
break;
|
length += buildMaze(length, width - 64 - length);
|
||||||
default:
|
break;
|
||||||
System.out
|
default:
|
||||||
.println("Cannot build level segment for unrecognized LevelComponent type: "
|
System.out
|
||||||
+ type);
|
.println("Cannot build level segment for unrecognized LevelComponent type: "
|
||||||
|
+ type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Total length built: " + length);
|
System.out.println("Total length built: " + length);
|
||||||
|
|
||||||
/*
|
|
||||||
* Original non-PCG code: // create the start location int length =
|
|
||||||
* buildStraight(0, width, true); length += buildPipeJump(length, width
|
|
||||||
* - length); // length += buildMaze(length, width - length);
|
|
||||||
*
|
|
||||||
* // create all of the medium sections while (length < width - 64) {
|
|
||||||
* length += buildStraight(length, width - length, true); }
|
|
||||||
*/
|
|
||||||
// set the end piece
|
// set the end piece
|
||||||
int floor = height - 1 - random.nextInt(4);
|
int floor = height - 1 - random.nextInt(4);
|
||||||
|
|
||||||
@@ -1187,71 +1182,10 @@ public class PCGLevel extends Level {
|
|||||||
: Level.BLOCK_COIN);
|
: Level.BLOCK_COIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (!safe) {
|
|
||||||
// if (length > 5) {
|
|
||||||
// decorate(xo, xo + length, floor);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void decorate(int xStart, int xLength, int floor) {
|
|
||||||
// // if its at the very top, just return
|
|
||||||
// if (floor < 1)
|
|
||||||
// return;
|
|
||||||
//
|
|
||||||
// // boolean coins = random.nextInt(3) == 0;
|
|
||||||
// boolean rocks = true;
|
|
||||||
//
|
|
||||||
// // add an enemy line above the box
|
|
||||||
// addEnemyLine(xStart + 1, xLength - 1, floor - 1);
|
|
||||||
//
|
|
||||||
// int s = random.nextInt(4);
|
|
||||||
// int e = random.nextInt(4);
|
|
||||||
//
|
|
||||||
// if (floor - 2 > 0) {
|
|
||||||
// if ((xLength - 1 - e) - (xStart + 1 + s) > 1) {
|
|
||||||
// for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
|
||||||
// setBlock(x, floor - 2, COIN);
|
|
||||||
// COINS++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// s = random.nextInt(4);
|
|
||||||
// e = random.nextInt(4);
|
|
||||||
//
|
|
||||||
// // this fills the set of blocks and the hidden objects inside them
|
|
||||||
// if (floor - 4 > 0) {
|
|
||||||
// if ((xLength - 1 - e) - (xStart + 1 + s) > 2) {
|
|
||||||
// for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
|
||||||
// if (rocks) {
|
|
||||||
// if (x != xStart + 1 && x != xLength - 2
|
|
||||||
// && random.nextInt(3) == 0) {
|
|
||||||
// if (random.nextInt(4) == 0) {
|
|
||||||
// setBlock(x, floor - 4, BLOCK_POWERUP);
|
|
||||||
// BLOCKS_POWER++;
|
|
||||||
// } else { // the fills a block with a hidden coin
|
|
||||||
// setBlock(x, floor - 4, BLOCK_COIN);
|
|
||||||
// BLOCKS_COINS++;
|
|
||||||
// }
|
|
||||||
// } else if (random.nextInt(4) == 0) {
|
|
||||||
// if (random.nextInt(4) == 0) {
|
|
||||||
// setBlock(x, floor - 4, (byte) (2 + 1 * 16));
|
|
||||||
// } else {
|
|
||||||
// setBlock(x, floor - 4, (byte) (1 + 1 * 16));
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// setBlock(x, floor - 4, BLOCK_EMPTY);
|
|
||||||
// BLOCKS_EMPTY++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void fixWalls() {
|
private void fixWalls() {
|
||||||
boolean[][] blockMap = new boolean[width + 1][height + 1];
|
boolean[][] blockMap = new boolean[width + 1][height + 1];
|
||||||
|
|
||||||
@@ -1271,4 +1205,4 @@ public class PCGLevel extends Level {
|
|||||||
blockify(this, blockMap, width + 1, height + 1);
|
blockify(this, blockMap, width + 1, height + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -41,4 +41,19 @@ public class AndClause implements Clause {
|
|||||||
public boolean isVariable() {
|
public boolean isVariable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (subClauses.size() == 0) {
|
||||||
|
return "(Empty AND clause)";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("(");
|
||||||
|
for (int i = 0; i < subClauses.size() - 1; i ++) {
|
||||||
|
sb.append(subClauses.get(i).toString());
|
||||||
|
sb.append(" AND ");
|
||||||
|
}
|
||||||
|
sb.append(subClauses.get(subClauses.size()-1).toString());
|
||||||
|
sb.append(")");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,8 +15,8 @@ public class LevelGrammarFactory {
|
|||||||
Variable v_HI_LO = new Variable("HI_LO", LevelComponent.TYPE.HI_LO);
|
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_LO_PATH = new Variable("LO_PATH", LevelComponent.TYPE.LO_PATH);
|
||||||
Variable v_HI_PATH = new Variable("HI_PATH", LevelComponent.TYPE.HI_PATH);
|
Variable v_HI_PATH = new Variable("HI_PATH", LevelComponent.TYPE.HI_PATH);
|
||||||
Variable v_lo_path = new Variable("lo_path", LevelComponent.TYPE.LO_PATH);
|
Variable v_lo_path = new Variable("lo_path", LevelComponent.TYPE.FLAT_LO);
|
||||||
Variable v_hi_path = new Variable("hi_path", LevelComponent.TYPE.HI_PATH);
|
Variable v_hi_path = new Variable("hi_path", LevelComponent.TYPE.FLAT_HI);
|
||||||
|
|
||||||
grammar.addVariable(v_START);
|
grammar.addVariable(v_START);
|
||||||
grammar.addVariable(v_LAND_SEGMENT);
|
grammar.addVariable(v_LAND_SEGMENT);
|
||||||
|
|||||||
@@ -56,4 +56,21 @@ public class OrClause implements Clause {
|
|||||||
public boolean isVariable() {
|
public boolean isVariable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (subClauses.size() == 0) {
|
||||||
|
return "(Empty OR clause)";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("(");
|
||||||
|
for (int i = 0; i < subClauses.size() - 1; i ++) {
|
||||||
|
sb.append(subClauses.get(i).toString());
|
||||||
|
sb.append(" OR ");
|
||||||
|
}
|
||||||
|
sb.append(subClauses.get(subClauses.size()-1).toString());
|
||||||
|
sb.append(")");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package dk.itu.mario.level.grammar;
|
package dk.itu.mario.level.grammar;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import dk.itu.mario.level.LevelComponent;
|
import dk.itu.mario.level.LevelComponent;
|
||||||
|
|
||||||
public class ParseNode {
|
public class ParseNode {
|
||||||
|
private static final DecimalFormat FORMATTER = new DecimalFormat("###.00");
|
||||||
private LevelComponent.TYPE levelCompType;
|
private LevelComponent.TYPE levelCompType;
|
||||||
private double percentLength;
|
private double percentLength;
|
||||||
private List<ParseNode> children = new ArrayList<ParseNode>();
|
private List<ParseNode> children = new ArrayList<ParseNode>();
|
||||||
@@ -59,4 +61,8 @@ public class ParseNode {
|
|||||||
public void setPercentLength(double percentLength) {
|
public void setPercentLength(double percentLength) {
|
||||||
this.percentLength = percentLength;
|
this.percentLength = percentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return levelCompType + " (" + FORMATTER.format(percentLength * 100) + "%)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user