From b431d5efeb38e458ce39ba4ccb262b76daa7bd4b Mon Sep 17 00:00:00 2001 From: Woody Folsom Date: Sun, 18 Mar 2012 08:09:53 -0400 Subject: [PATCH] Functional context-free grammar! Worked first time! Well... almost. --- src/dk/itu/mario/level/PCGLevel.java | 112 ++++-------------- src/dk/itu/mario/level/grammar/AndClause.java | 15 +++ .../level/grammar/LevelGrammarFactory.java | 4 +- src/dk/itu/mario/level/grammar/OrClause.java | 17 +++ src/dk/itu/mario/level/grammar/ParseNode.java | 6 + 5 files changed, 63 insertions(+), 91 deletions(-) diff --git a/src/dk/itu/mario/level/PCGLevel.java b/src/dk/itu/mario/level/PCGLevel.java index cd17649..a250521 100644 --- a/src/dk/itu/mario/level/PCGLevel.java +++ b/src/dk/itu/mario/level/PCGLevel.java @@ -21,7 +21,8 @@ public class PCGLevel extends Level { public static int COIN_REWARD = 1; 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; private static Random levelSeedRandom = new Random(); @@ -181,38 +182,32 @@ public class PCGLevel extends Level { for (LevelComponent lcomp : levelTemplate) { LevelComponent.TYPE lctype = lcomp.getType(); System.out.println("Building for: " + lcomp); - switch (lctype) { - case FLAT_LO: - case FLAT_HI: - length += buildStraight(length, lcomp.getEnd(), true); - break; - case PIPE_JUMP: - length += buildPipeJump(length, width - 64 - length); - break; - case PLATFORM_JUMP: - length += buildPlatformJump(length, width - 64 - length); - break; - case MAZE: - length += buildMaze(length, width - 64 - length); - break; - default: - System.out - .println("Cannot build level segment for unrecognized LevelComponent type: " - + type); + while (length < Math.min(width - 64, lcomp.getEnd())) { + switch (lctype) { + case FLAT_LO: + case FLAT_HI: + length += buildStraight(length, lcomp.getEnd(), true); + break; + case PIPE_JUMP: + length += buildPipeJump(length, width - 64 - length); + break; + case PLATFORM_JUMP: + length += buildPlatformJump(length, width - 64 - length); + break; + case MAZE: + length += buildMaze(length, width - 64 - length); + break; + default: + System.out + .println("Cannot build level segment for unrecognized LevelComponent type: " + + type); + } } } } 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 int floor = height - 1 - random.nextInt(4); @@ -1187,71 +1182,10 @@ public class PCGLevel extends Level { : Level.BLOCK_COIN); } } - // if (!safe) { - // if (length > 5) { - // decorate(xo, xo + length, floor); - // } - // } 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() { boolean[][] blockMap = new boolean[width + 1][height + 1]; @@ -1271,4 +1205,4 @@ public class PCGLevel extends Level { blockify(this, blockMap, width + 1, height + 1); } -} +} \ No newline at end of file diff --git a/src/dk/itu/mario/level/grammar/AndClause.java b/src/dk/itu/mario/level/grammar/AndClause.java index b70cce9..f2a901a 100644 --- a/src/dk/itu/mario/level/grammar/AndClause.java +++ b/src/dk/itu/mario/level/grammar/AndClause.java @@ -41,4 +41,19 @@ public class AndClause implements Clause { public boolean isVariable() { 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(); + } } \ No newline at end of file diff --git a/src/dk/itu/mario/level/grammar/LevelGrammarFactory.java b/src/dk/itu/mario/level/grammar/LevelGrammarFactory.java index a73add9..12eb60e 100644 --- a/src/dk/itu/mario/level/grammar/LevelGrammarFactory.java +++ b/src/dk/itu/mario/level/grammar/LevelGrammarFactory.java @@ -15,8 +15,8 @@ public class LevelGrammarFactory { 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.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); diff --git a/src/dk/itu/mario/level/grammar/OrClause.java b/src/dk/itu/mario/level/grammar/OrClause.java index 5a97c53..4934d67 100644 --- a/src/dk/itu/mario/level/grammar/OrClause.java +++ b/src/dk/itu/mario/level/grammar/OrClause.java @@ -56,4 +56,21 @@ public class OrClause implements Clause { public boolean isVariable() { 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(); + } } \ No newline at end of file diff --git a/src/dk/itu/mario/level/grammar/ParseNode.java b/src/dk/itu/mario/level/grammar/ParseNode.java index 92ea206..5b8a65c 100644 --- a/src/dk/itu/mario/level/grammar/ParseNode.java +++ b/src/dk/itu/mario/level/grammar/ParseNode.java @@ -1,11 +1,13 @@ package dk.itu.mario.level.grammar; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import dk.itu.mario.level.LevelComponent; public class ParseNode { + private static final DecimalFormat FORMATTER = new DecimalFormat("###.00"); private LevelComponent.TYPE levelCompType; private double percentLength; private List children = new ArrayList(); @@ -59,4 +61,8 @@ public class ParseNode { public void setPercentLength(double percentLength) { this.percentLength = percentLength; } + + public String toString() { + return levelCompType + " (" + FORMATTER.format(percentLength * 100) + "%)"; + } } \ No newline at end of file