From dc6fe7e4938e02a55f2b4226b687852bd54fbb42 Mon Sep 17 00:00:00 2001 From: Marshall Date: Sun, 18 Mar 2012 13:01:51 -0400 Subject: [PATCH] - 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. --- src/dk/itu/mario/level/PCGLevel.java | 79 +++++++++++++++++----------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/src/dk/itu/mario/level/PCGLevel.java b/src/dk/itu/mario/level/PCGLevel.java index f01b838..3cbade8 100644 --- a/src/dk/itu/mario/level/PCGLevel.java +++ b/src/dk/itu/mario/level/PCGLevel.java @@ -40,6 +40,10 @@ public class PCGLevel extends Level { private int type; private Random random; + public enum ChallengeType { + GAP, ENEMY, HARDER_ENEMY, JUMP + }; + public PCGLevel(int width, int height) { super(width, height); } @@ -80,13 +84,16 @@ public class PCGLevel extends Level { LevelGrammar grammar; try { 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("==== LEVEL GRAMMAR ===="); System.out.println(grammar); System.out.println("======================="); } 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."); grammar = LevelGrammarFactory.createGrammar(); } @@ -138,7 +145,6 @@ public class PCGLevel extends Level { int length = 0; if (TESTING) { - difficulty = 10; int minElements = 5; int maxLen; int elementsSoFar = 0; @@ -188,19 +194,22 @@ public class PCGLevel extends Level { else { System.out.println("Generating level for component list: "); LevelParseTree parseTree = grammar.generateRandomTree(seed, width); - + int MAX_REGENS = 10; int nRegens = 0; - while (!FitnessEvaluator.isFit(parseTree,profile,archetype) && nRegens < MAX_REGENS) { - System.out.println("Generated level is NOT fit. Regenerating..."); + while (!FitnessEvaluator.isFit(parseTree, profile, archetype) + && nRegens < MAX_REGENS) { + System.out + .println("Generated level is NOT fit. Regenerating..."); parseTree = grammar.generateRandomTree(seed, width); nRegens++; } - + 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 levelTemplate = parseTree.getLevelTemplate(); for (LevelComponent lcomp : levelTemplate) { @@ -286,8 +295,10 @@ public class PCGLevel extends Level { if (x == 3) { setBlock(xo + x, floor - 1, Level.CANNON_MIDDLE); setBlock(xo + x, floor - 2, Level.CANNON_TOP); - setBlock(xo + x, floor - 3, - shouldAddChallenge() ? Level.CANNON_TOP + setBlock( + xo + x, + floor - 3, + shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? Level.CANNON_TOP : Level.CANNON_MIDDLE); setBlock(xo + x, floor - 4, Level.CANNON_TOP); } @@ -403,14 +414,14 @@ public class PCGLevel extends Level { if (maxLength >= 26) { 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.GOOMPA; int reward = shouldAddReward(); boolean arc = random.nextBoolean(); int numEnemies = 0; for (int i = 0; i < 10; i++) { - numEnemies += shouldAddChallenge() ? 1 : 0; + numEnemies += shouldAddChallenge(ChallengeType.ENEMY) ? 1 : 0; } // Create the pit. @@ -490,11 +501,12 @@ public class PCGLevel extends Level { private int buildLemmingTrap(int xo, int maxLength) { if (maxLength >= 14) { 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.GOOMPA; - boolean flying = shouldAddChallenge() && shouldAddChallenge() - && shouldAddChallenge(); + boolean flying = shouldAddChallenge(ChallengeType.HARDER_ENEMY) + && shouldAddChallenge(ChallengeType.HARDER_ENEMY) + && shouldAddChallenge(ChallengeType.HARDER_ENEMY); int reward = shouldAddReward(); 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 // randomly add difficulty based on the user's skill level. - private boolean shouldAddChallenge() { + private boolean shouldAddChallenge(ChallengeType ct) { return random.nextInt(11) + 1 <= difficulty; } @@ -792,9 +804,9 @@ public class PCGLevel extends Level { 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.GREEN_TURTLE) : SpriteTemplate.GOOMPA; @@ -836,10 +848,11 @@ public class PCGLevel extends Level { int pipeHeight; int gap = 0; boolean space; - boolean deadGaps = shouldAddChallenge(); + boolean deadGaps = shouldAddChallenge(ChallengeType.GAP); int numPipes; - for (numPipes = 0; shouldAddChallenge(); numPipes++) { + for (numPipes = 0; shouldAddChallenge(deadGaps ? ChallengeType.GAP + : ChallengeType.JUMP); numPipes++) { } localHeight = random.nextInt(2) + 1; @@ -866,7 +879,7 @@ public class PCGLevel extends Level { setBlock(xo + length + 1, this.height - 1 - y, Level.TUBE_TOP_RIGHT); - if (shouldAddChallenge()) { + if (shouldAddChallenge(ChallengeType.ENEMY)) { setSpriteTemplate(xo + length, this.height - y, new SpriteTemplate( SpriteTemplate.JUMP_FLOWER, false)); @@ -889,7 +902,7 @@ public class PCGLevel extends Level { } for (gap = 0; gap < 4 && length + gap <= maxLength - && shouldAddChallenge(); gap++) { + && shouldAddChallenge(ChallengeType.JUMP); gap++) { if (!deadGaps) { for (int y = 0; y < midFloor; y++) { @@ -913,7 +926,8 @@ public class PCGLevel extends Level { int length = 0; int gapLength; - for (gapLength = 1; shouldAddChallenge() && gapLength < 4; gapLength++) { + for (gapLength = 1; shouldAddChallenge(ChallengeType.JUMP) + && gapLength < 4; gapLength++) { } int maxNumPlatforms = (maxLength - 3) / (4 + gapLength); @@ -922,7 +936,10 @@ public class PCGLevel extends Level { return 0; } - int numPlatforms = random.nextInt(maxNumPlatforms); + int numPlatforms; + for (numPlatforms = 0; numPlatforms < maxNumPlatforms + && shouldAddChallenge(ChallengeType.GAP); numPlatforms++) { + } if (numPlatforms > 1) { boolean found = false; @@ -1024,10 +1041,10 @@ public class PCGLevel extends Level { setBlock(xo + length + 2, 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 - : (shouldAddChallenge() ? (shouldAddChallenge() ? SpriteTemplate.ARMORED_TURTLE + : (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? (shouldAddChallenge(ChallengeType.HARDER_ENEMY) ? SpriteTemplate.ARMORED_TURTLE : SpriteTemplate.GREEN_TURTLE) : SpriteTemplate.GOOMPA); @@ -1036,7 +1053,7 @@ public class PCGLevel extends Level { this.height - heightMod - 1, new SpriteTemplate( enemyType, - (enemyType == SpriteTemplate.RED_TURTLE && shouldAddChallenge()) + (enemyType == SpriteTemplate.RED_TURTLE && shouldAddChallenge(ChallengeType.HARDER_ENEMY)) || enemyType != SpriteTemplate.RED_TURTLE)); } @@ -1095,8 +1112,8 @@ public class PCGLevel extends Level { } } - if (shouldAddChallenge() && allowEnemies) { - int enemyType = shouldAddChallenge() ? (shouldAddChallenge() ? (shouldAddChallenge() ? (shouldAddChallenge() + if (shouldAddChallenge(ChallengeType.ENEMY) && allowEnemies) { + 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 : SpriteTemplate.CANNON_BALL) : SpriteTemplate.RED_TURTLE) @@ -1131,7 +1148,7 @@ public class PCGLevel extends Level { else { setSpriteTemplate(xo + (length / 2), floor - 1, - new SpriteTemplate(enemyType, shouldAddChallenge())); + new SpriteTemplate(enemyType, shouldAddChallenge(ChallengeType.HARDER_ENEMY))); } }