- Added the notion of "challenge type" difficulty weighting. It doesn't do anything yet, but the scaffolding is there. Create a set of enums to aid that.

- Added more precise platform number randomizing in the platform jump challenge.
- Removed the hard-coded difficulty in the testing generation branch.
This commit is contained in:
Marshall
2012-03-18 13:01:51 -04:00
parent 554e9af319
commit dc6fe7e493

View File

@@ -40,6 +40,10 @@ public class PCGLevel extends Level {
private int type; private int type;
private Random random; private Random random;
public enum ChallengeType {
GAP, ENEMY, HARDER_ENEMY, JUMP
};
public PCGLevel(int width, int height) { public PCGLevel(int width, int height) {
super(width, height); super(width, height);
} }
@@ -80,13 +84,16 @@ public class PCGLevel extends Level {
LevelGrammar grammar; LevelGrammar grammar;
try { try {
String grammarFileName = "grammars/overland.grm"; String grammarFileName = "grammars/overland.grm";
grammar = LevelGrammarFactory.createGrammar(new File(grammarFileName)); grammar = LevelGrammarFactory.createGrammar(new File(
grammarFileName));
System.out.println("Read grammar from file: " + grammarFileName); System.out.println("Read grammar from file: " + grammarFileName);
System.out.println("==== LEVEL GRAMMAR ===="); System.out.println("==== LEVEL GRAMMAR ====");
System.out.println(grammar); System.out.println(grammar);
System.out.println("======================="); System.out.println("=======================");
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("Failed to parse grammar file due to exception: " + ex.getMessage()); System.out
.println("Failed to parse grammar file due to exception: "
+ ex.getMessage());
System.out.println("Defaulting to basic overland grammar."); System.out.println("Defaulting to basic overland grammar.");
grammar = LevelGrammarFactory.createGrammar(); grammar = LevelGrammarFactory.createGrammar();
} }
@@ -138,7 +145,6 @@ public class PCGLevel extends Level {
int length = 0; int length = 0;
if (TESTING) { if (TESTING) {
difficulty = 10;
int minElements = 5; int minElements = 5;
int maxLen; int maxLen;
int elementsSoFar = 0; int elementsSoFar = 0;
@@ -191,14 +197,17 @@ public class PCGLevel extends Level {
int MAX_REGENS = 10; int MAX_REGENS = 10;
int nRegens = 0; int nRegens = 0;
while (!FitnessEvaluator.isFit(parseTree,profile,archetype) && nRegens < MAX_REGENS) { while (!FitnessEvaluator.isFit(parseTree, profile, archetype)
System.out.println("Generated level is NOT fit. Regenerating..."); && nRegens < MAX_REGENS) {
System.out
.println("Generated level is NOT fit. Regenerating...");
parseTree = grammar.generateRandomTree(seed, width); parseTree = grammar.generateRandomTree(seed, width);
nRegens++; nRegens++;
} }
if (nRegens == MAX_REGENS) { if (nRegens == MAX_REGENS) {
System.out.println("Failed to generate a fit level after " + nRegens + " attempts. Proceeding with unfit level."); System.out.println("Failed to generate a fit level after "
+ nRegens + " attempts. Proceeding with unfit level.");
} }
List<LevelComponent> levelTemplate = parseTree.getLevelTemplate(); List<LevelComponent> levelTemplate = parseTree.getLevelTemplate();
@@ -286,8 +295,10 @@ public class PCGLevel extends Level {
if (x == 3) { if (x == 3) {
setBlock(xo + x, floor - 1, Level.CANNON_MIDDLE); setBlock(xo + x, floor - 1, Level.CANNON_MIDDLE);
setBlock(xo + x, floor - 2, Level.CANNON_TOP); setBlock(xo + x, floor - 2, Level.CANNON_TOP);
setBlock(xo + x, floor - 3, setBlock(
shouldAddChallenge() ? Level.CANNON_TOP xo + x,
floor - 3,
shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? Level.CANNON_TOP
: Level.CANNON_MIDDLE); : Level.CANNON_MIDDLE);
setBlock(xo + x, floor - 4, Level.CANNON_TOP); setBlock(xo + x, floor - 4, Level.CANNON_TOP);
} }
@@ -403,14 +414,14 @@ public class PCGLevel extends Level {
if (maxLength >= 26) { if (maxLength >= 26) {
int floor = height - 1 - random.nextInt(4); int floor = height - 1 - random.nextInt(4);
int enemyType = shouldAddChallenge() ? (shouldAddChallenge() ? SpriteTemplate.ARMORED_TURTLE int enemyType = shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? SpriteTemplate.ARMORED_TURTLE
: SpriteTemplate.GREEN_TURTLE) : SpriteTemplate.GREEN_TURTLE)
: SpriteTemplate.GOOMPA; : SpriteTemplate.GOOMPA;
int reward = shouldAddReward(); int reward = shouldAddReward();
boolean arc = random.nextBoolean(); boolean arc = random.nextBoolean();
int numEnemies = 0; int numEnemies = 0;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
numEnemies += shouldAddChallenge() ? 1 : 0; numEnemies += shouldAddChallenge(ChallengeType.ENEMY) ? 1 : 0;
} }
// Create the pit. // Create the pit.
@@ -490,11 +501,12 @@ public class PCGLevel extends Level {
private int buildLemmingTrap(int xo, int maxLength) { private int buildLemmingTrap(int xo, int maxLength) {
if (maxLength >= 14) { if (maxLength >= 14) {
int floor = height - 1 - random.nextInt(4); int floor = height - 1 - random.nextInt(4);
int enemyType = shouldAddChallenge() ? (shouldAddChallenge() ? SpriteTemplate.ARMORED_TURTLE int enemyType = shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? SpriteTemplate.ARMORED_TURTLE
: SpriteTemplate.GREEN_TURTLE) : SpriteTemplate.GREEN_TURTLE)
: SpriteTemplate.GOOMPA; : SpriteTemplate.GOOMPA;
boolean flying = shouldAddChallenge() && shouldAddChallenge() boolean flying = shouldAddChallenge(ChallengeType.HARDER_ENEMY)
&& shouldAddChallenge(); && shouldAddChallenge(ChallengeType.HARDER_ENEMY)
&& shouldAddChallenge(ChallengeType.HARDER_ENEMY);
int reward = shouldAddReward(); int reward = shouldAddReward();
for (int x = 0; x < 18; x++) { for (int x = 0; x < 18; x++) {
@@ -658,7 +670,7 @@ public class PCGLevel extends Level {
// This is basically just a randomizer function to call whenever I need to // This is basically just a randomizer function to call whenever I need to
// randomly add difficulty based on the user's skill level. // randomly add difficulty based on the user's skill level.
private boolean shouldAddChallenge() { private boolean shouldAddChallenge(ChallengeType ct) {
return random.nextInt(11) + 1 <= difficulty; return random.nextInt(11) + 1 <= difficulty;
} }
@@ -792,9 +804,9 @@ public class PCGLevel extends Level {
setBlock(xo + soFar + x, this.height - 4, Level.ROCK); setBlock(xo + soFar + x, this.height - 4, Level.ROCK);
} }
if (addEnemy && shouldAddChallenge()) { if (addEnemy && shouldAddChallenge(ChallengeType.ENEMY)) {
enemyType = shouldAddChallenge() ? (shouldAddChallenge() ? (shouldAddChallenge() ? SpriteTemplate.ARMORED_TURTLE enemyType = shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? SpriteTemplate.ARMORED_TURTLE
: SpriteTemplate.RED_TURTLE) : SpriteTemplate.RED_TURTLE)
: SpriteTemplate.GREEN_TURTLE) : SpriteTemplate.GREEN_TURTLE)
: SpriteTemplate.GOOMPA; : SpriteTemplate.GOOMPA;
@@ -836,10 +848,11 @@ public class PCGLevel extends Level {
int pipeHeight; int pipeHeight;
int gap = 0; int gap = 0;
boolean space; boolean space;
boolean deadGaps = shouldAddChallenge(); boolean deadGaps = shouldAddChallenge(ChallengeType.GAP);
int numPipes; int numPipes;
for (numPipes = 0; shouldAddChallenge(); numPipes++) { for (numPipes = 0; shouldAddChallenge(deadGaps ? ChallengeType.GAP
: ChallengeType.JUMP); numPipes++) {
} }
localHeight = random.nextInt(2) + 1; localHeight = random.nextInt(2) + 1;
@@ -866,7 +879,7 @@ public class PCGLevel extends Level {
setBlock(xo + length + 1, this.height - 1 - y, setBlock(xo + length + 1, this.height - 1 - y,
Level.TUBE_TOP_RIGHT); Level.TUBE_TOP_RIGHT);
if (shouldAddChallenge()) { if (shouldAddChallenge(ChallengeType.ENEMY)) {
setSpriteTemplate(xo + length, this.height - y, setSpriteTemplate(xo + length, this.height - y,
new SpriteTemplate( new SpriteTemplate(
SpriteTemplate.JUMP_FLOWER, false)); SpriteTemplate.JUMP_FLOWER, false));
@@ -889,7 +902,7 @@ public class PCGLevel extends Level {
} }
for (gap = 0; gap < 4 && length + gap <= maxLength for (gap = 0; gap < 4 && length + gap <= maxLength
&& shouldAddChallenge(); gap++) { && shouldAddChallenge(ChallengeType.JUMP); gap++) {
if (!deadGaps) { if (!deadGaps) {
for (int y = 0; y < midFloor; y++) { for (int y = 0; y < midFloor; y++) {
@@ -913,7 +926,8 @@ public class PCGLevel extends Level {
int length = 0; int length = 0;
int gapLength; int gapLength;
for (gapLength = 1; shouldAddChallenge() && gapLength < 4; gapLength++) { for (gapLength = 1; shouldAddChallenge(ChallengeType.JUMP)
&& gapLength < 4; gapLength++) {
} }
int maxNumPlatforms = (maxLength - 3) / (4 + gapLength); int maxNumPlatforms = (maxLength - 3) / (4 + gapLength);
@@ -922,7 +936,10 @@ public class PCGLevel extends Level {
return 0; return 0;
} }
int numPlatforms = random.nextInt(maxNumPlatforms); int numPlatforms;
for (numPlatforms = 0; numPlatforms < maxNumPlatforms
&& shouldAddChallenge(ChallengeType.GAP); numPlatforms++) {
}
if (numPlatforms > 1) { if (numPlatforms > 1) {
boolean found = false; boolean found = false;
@@ -1024,10 +1041,10 @@ public class PCGLevel extends Level {
setBlock(xo + length + 2, this.height - heightMod, Level.ROCK); setBlock(xo + length + 2, this.height - heightMod, Level.ROCK);
setBlock(xo + length + 3, this.height - heightMod, Level.ROCK); setBlock(xo + length + 3, this.height - heightMod, Level.ROCK);
if (shouldAddChallenge()) { if (shouldAddChallenge(ChallengeType.ENEMY)) {
enemyType = random.nextBoolean() ? SpriteTemplate.RED_TURTLE enemyType = random.nextBoolean() ? SpriteTemplate.RED_TURTLE
: (shouldAddChallenge() ? (shouldAddChallenge() ? SpriteTemplate.ARMORED_TURTLE : (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? SpriteTemplate.ARMORED_TURTLE
: SpriteTemplate.GREEN_TURTLE) : SpriteTemplate.GREEN_TURTLE)
: SpriteTemplate.GOOMPA); : SpriteTemplate.GOOMPA);
@@ -1036,7 +1053,7 @@ public class PCGLevel extends Level {
this.height - heightMod - 1, this.height - heightMod - 1,
new SpriteTemplate( new SpriteTemplate(
enemyType, enemyType,
(enemyType == SpriteTemplate.RED_TURTLE && shouldAddChallenge()) (enemyType == SpriteTemplate.RED_TURTLE && shouldAddChallenge(ChallengeType.HARDER_ENEMY))
|| enemyType != SpriteTemplate.RED_TURTLE)); || enemyType != SpriteTemplate.RED_TURTLE));
} }
@@ -1095,8 +1112,8 @@ public class PCGLevel extends Level {
} }
} }
if (shouldAddChallenge() && allowEnemies) { if (shouldAddChallenge(ChallengeType.ENEMY) && allowEnemies) {
int enemyType = shouldAddChallenge() ? (shouldAddChallenge() ? (shouldAddChallenge() ? (shouldAddChallenge() int enemyType = shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY)
|| (reward > 0 && length >= 5) ? SpriteTemplate.ARMORED_TURTLE || (reward > 0 && length >= 5) ? SpriteTemplate.ARMORED_TURTLE
: SpriteTemplate.CANNON_BALL) : SpriteTemplate.CANNON_BALL)
: SpriteTemplate.RED_TURTLE) : SpriteTemplate.RED_TURTLE)
@@ -1131,7 +1148,7 @@ public class PCGLevel extends Level {
else { else {
setSpriteTemplate(xo + (length / 2), floor - 1, setSpriteTemplate(xo + (length / 2), floor - 1,
new SpriteTemplate(enemyType, shouldAddChallenge())); new SpriteTemplate(enemyType, shouldAddChallenge(ChallengeType.HARDER_ENEMY)));
} }
} }