From e1aadadde49111f1a1773bc5515fdba998b496f6 Mon Sep 17 00:00:00 2001 From: Woody Folsom Date: Sat, 17 Mar 2012 11:49:50 -0400 Subject: [PATCH] Implemented stub functionality for determining player Profile, level Archetype and generating Level Components using a simple grammar. See new method calls in MyNewLevel for an example of this level creation pipeline. --- src/dk/itu/mario/level/MyNewLevel.java | 21 +++++++ .../level/generator/ArchetypeMatcher.java | 12 ++++ .../mario/level/generator/GrammarTuner.java | 7 +++ .../mario/level/generator/LevelArchetype.java | 31 ++++++++++ .../mario/level/generator/LevelGrammar.java | 58 +++++++++++++++++++ .../level/generator/LevelGrammarFactory.java | 21 +++++++ .../mario/level/generator/PlayerProfile.java | 29 ++++++++++ .../mario/level/generator/ProductionRule.java | 25 ++++++++ .../mario/level/generator/ProfileMatcher.java | 13 +++++ .../itu/mario/level/generator/Variable.java | 27 +++++++++ 10 files changed, 244 insertions(+) create mode 100644 src/dk/itu/mario/level/generator/ArchetypeMatcher.java create mode 100644 src/dk/itu/mario/level/generator/GrammarTuner.java create mode 100644 src/dk/itu/mario/level/generator/LevelArchetype.java create mode 100644 src/dk/itu/mario/level/generator/LevelGrammar.java create mode 100644 src/dk/itu/mario/level/generator/LevelGrammarFactory.java create mode 100644 src/dk/itu/mario/level/generator/PlayerProfile.java create mode 100644 src/dk/itu/mario/level/generator/ProductionRule.java create mode 100644 src/dk/itu/mario/level/generator/ProfileMatcher.java create mode 100644 src/dk/itu/mario/level/generator/Variable.java diff --git a/src/dk/itu/mario/level/MyNewLevel.java b/src/dk/itu/mario/level/MyNewLevel.java index 2f59e67..8c7cb17 100644 --- a/src/dk/itu/mario/level/MyNewLevel.java +++ b/src/dk/itu/mario/level/MyNewLevel.java @@ -8,6 +8,13 @@ import dk.itu.mario.MarioInterface.LevelInterface; import dk.itu.mario.engine.DataRecorder; import dk.itu.mario.engine.sprites.Enemy; import dk.itu.mario.engine.sprites.SpriteTemplate; +import dk.itu.mario.level.generator.ArchetypeMatcher; +import dk.itu.mario.level.generator.GrammarTuner; +import dk.itu.mario.level.generator.LevelArchetype; +import dk.itu.mario.level.generator.LevelGrammar; +import dk.itu.mario.level.generator.LevelGrammarFactory; +import dk.itu.mario.level.generator.PlayerProfile; +import dk.itu.mario.level.generator.ProfileMatcher; public class MyNewLevel extends Level { public enum MazeLevel { @@ -51,6 +58,20 @@ public class MyNewLevel extends Level { System.out.println("Generating level based on previous GamePlay AND DataRecorder metrics."); this.dataRecorder = dataRecorder; + PlayerProfile profile = ProfileMatcher.getMatchingProfile(playerMetrics, dataRecorder); + System.out.println("PlayerProfile: " + profile); + + LevelArchetype archetype = ArchetypeMatcher.getMatchingArchetype(playerMetrics, dataRecorder); + System.out.println("LevelArchetype: " + archetype); + + System.out.println("Creating level grammar"); + LevelGrammar grammar = LevelGrammarFactory.createGrammar(profile, archetype); + + System.out.println("Tuning grammar for PlayerProfile & LevelArchetype using RETE"); + grammar = GrammarTuner.tune(grammar,profile, archetype); + + System.out.println("Sample level parameters: " + + grammar.generateRandom(seed)); create(seed, difficulty, type); } diff --git a/src/dk/itu/mario/level/generator/ArchetypeMatcher.java b/src/dk/itu/mario/level/generator/ArchetypeMatcher.java new file mode 100644 index 0000000..0a82476 --- /dev/null +++ b/src/dk/itu/mario/level/generator/ArchetypeMatcher.java @@ -0,0 +1,12 @@ +package dk.itu.mario.level.generator; + +import dk.itu.mario.MarioInterface.GamePlay; +import dk.itu.mario.engine.DataRecorder; +import dk.itu.mario.level.generator.LevelArchetype.TYPE; + +public class ArchetypeMatcher { + public static LevelArchetype getMatchingArchetype(GamePlay playerMetrics, DataRecorder detailedInfo) { + System.out.println("Selecting PlayerProfile based on GamePlay metrics, DataRecorder logs."); + return new LevelArchetype(TYPE.OVERGROUND,1); + } +} diff --git a/src/dk/itu/mario/level/generator/GrammarTuner.java b/src/dk/itu/mario/level/generator/GrammarTuner.java new file mode 100644 index 0000000..e050ec2 --- /dev/null +++ b/src/dk/itu/mario/level/generator/GrammarTuner.java @@ -0,0 +1,7 @@ +package dk.itu.mario.level.generator; + +public class GrammarTuner { + public static LevelGrammar tune(LevelGrammar grammar, PlayerProfile profile, LevelArchetype archetype) { + return grammar; + } +} diff --git a/src/dk/itu/mario/level/generator/LevelArchetype.java b/src/dk/itu/mario/level/generator/LevelArchetype.java new file mode 100644 index 0000000..989433d --- /dev/null +++ b/src/dk/itu/mario/level/generator/LevelArchetype.java @@ -0,0 +1,31 @@ +package dk.itu.mario.level.generator; + +public class LevelArchetype { + public static final int MAX_DIFFICULTY_LEVEL = 10; + //The canonical Super Mario level types. + public enum TYPE {OVERGROUND, UNDERGROUND, CASTLE} + + private int difficultyLevel; + private TYPE type; + + public LevelArchetype(TYPE type, int difficultyLevel) { + if (difficultyLevel < 1 || difficultyLevel > MAX_DIFFICULTY_LEVEL) { + throw new IllegalArgumentException("DifficultyLevel must be in the range [1.." + MAX_DIFFICULTY_LEVEL +"]"); + } + this.difficultyLevel = difficultyLevel; + this.type = type; + } + + public int getDifficultyLevel() { + return difficultyLevel; + } + + public TYPE getType() { + return type; + } + + @Override + public String toString() { + return type + " (Difficulty " + difficultyLevel + "/" + MAX_DIFFICULTY_LEVEL+")"; + } +} diff --git a/src/dk/itu/mario/level/generator/LevelGrammar.java b/src/dk/itu/mario/level/generator/LevelGrammar.java new file mode 100644 index 0000000..cbd298c --- /dev/null +++ b/src/dk/itu/mario/level/generator/LevelGrammar.java @@ -0,0 +1,58 @@ +package dk.itu.mario.level.generator; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; + +public class LevelGrammar { + private Variable start; + private Map ruleMap = new HashMap(); + private Set variables = new TreeSet(); + + public void addVariable(Variable var) { + if (variables.contains(var)) { + throw new IllegalArgumentException( + "Grammar already contains variable: " + var); + } + variables.add(var); + } + + public void addProductionRule(ProductionRule rule) { + if (ruleMap.containsKey(rule.getLHS())) { + throw new IllegalArgumentException( + "Grammar already contains rule with LHS: " + rule.getLHS()); + } + ruleMap.put(rule.getLHS(), rule); + } + + public String generateRandom(long randomSeed) { + System.out.println("Generating random level parameters using seed: " + + randomSeed); + List startRuleRHS = getRule(getStart()).getRHS(); + StringBuilder sb = new StringBuilder(); + for (Variable var : startRuleRHS) { + sb.append(var.toString()); + } + return sb.toString(); + } + + public String generateRandom() { + System.out.println("Creating new random seed for LevelGrammar"); + return generateRandom(new Random().nextLong()); + } + + public ProductionRule getRule(Variable var) { + return ruleMap.get(var); + } + + public Variable getStart() { + return start; + } + + public void setStart(Variable start) { + this.start = start; + } +} diff --git a/src/dk/itu/mario/level/generator/LevelGrammarFactory.java b/src/dk/itu/mario/level/generator/LevelGrammarFactory.java new file mode 100644 index 0000000..239ab3e --- /dev/null +++ b/src/dk/itu/mario/level/generator/LevelGrammarFactory.java @@ -0,0 +1,21 @@ +package dk.itu.mario.level.generator; + + +public class LevelGrammarFactory { + public static LevelGrammar createGrammar(PlayerProfile playerProfile, LevelArchetype archetype) { + LevelGrammar grammar = new LevelGrammar(); + + Variable v_S = new Variable("S"); + Variable v_level_start = new Variable("level_start"); + Variable v_level_end = new Variable("level_end"); + + grammar.addVariable(v_S); + grammar.addVariable(v_level_start); + grammar.addVariable(v_level_end); + + grammar.addProductionRule(new ProductionRule(v_S,v_level_start,v_level_end)); + grammar.setStart(v_S); + + return grammar; + } +} diff --git a/src/dk/itu/mario/level/generator/PlayerProfile.java b/src/dk/itu/mario/level/generator/PlayerProfile.java new file mode 100644 index 0000000..9f2d546 --- /dev/null +++ b/src/dk/itu/mario/level/generator/PlayerProfile.java @@ -0,0 +1,29 @@ +package dk.itu.mario.level.generator; + +public class PlayerProfile { + //From Bartle/Yee models of player psychology: achiever, killer, explorer, manipulator + public enum TYPE { RUNNER, SHOOTER, JUMPER, BUMPER} + //Dreyfus model of skill acquisition: + public enum SKILL_LEVEL { NOVICE, BEGINNER, COMPETENT, PROFICIENT, EXPERT} + + private SKILL_LEVEL skillLevel; + private TYPE type; + + public PlayerProfile(SKILL_LEVEL skillLevel, TYPE type) { + this.skillLevel = skillLevel; + this .type = type; + } + + public SKILL_LEVEL getSkillLevel() { + return skillLevel; + } + + public TYPE getType() { + return type; + } + + @Override + public String toString() { + return skillLevel + " " + type; + } +} diff --git a/src/dk/itu/mario/level/generator/ProductionRule.java b/src/dk/itu/mario/level/generator/ProductionRule.java new file mode 100644 index 0000000..d98a9d9 --- /dev/null +++ b/src/dk/itu/mario/level/generator/ProductionRule.java @@ -0,0 +1,25 @@ +package dk.itu.mario.level.generator; + +import java.util.ArrayList; +import java.util.List; + +public class ProductionRule { + private Variable lhs; + private List rhs; + + public ProductionRule(Variable lhs, Variable... rhs) { + this.lhs = lhs; + this.rhs = new ArrayList(); + for (Variable var : rhs) { + this.rhs.add(var); + } + } + + public Variable getLHS() { + return lhs; + } + + public List getRHS() { + return rhs; + } +} \ No newline at end of file diff --git a/src/dk/itu/mario/level/generator/ProfileMatcher.java b/src/dk/itu/mario/level/generator/ProfileMatcher.java new file mode 100644 index 0000000..e2482fa --- /dev/null +++ b/src/dk/itu/mario/level/generator/ProfileMatcher.java @@ -0,0 +1,13 @@ +package dk.itu.mario.level.generator; + +import dk.itu.mario.MarioInterface.GamePlay; +import dk.itu.mario.engine.DataRecorder; +import dk.itu.mario.level.generator.PlayerProfile.SKILL_LEVEL; +import dk.itu.mario.level.generator.PlayerProfile.TYPE; + +public class ProfileMatcher { + public static PlayerProfile getMatchingProfile(GamePlay playerMetrics, DataRecorder detailedInfo) { + System.out.println("Selecting PlayerProfile based on GamePlay metrics, DataRecorder logs."); + return new PlayerProfile(SKILL_LEVEL.NOVICE, TYPE.RUNNER); + } +} diff --git a/src/dk/itu/mario/level/generator/Variable.java b/src/dk/itu/mario/level/generator/Variable.java new file mode 100644 index 0000000..2592994 --- /dev/null +++ b/src/dk/itu/mario/level/generator/Variable.java @@ -0,0 +1,27 @@ +package dk.itu.mario.level.generator; + +public class Variable implements Comparable { + private boolean terminal; + private String value; + + public Variable(String value) { + this.value = value; + this.terminal = (value.toLowerCase().equals(value)); + } + + public boolean isTerminal() { + return terminal; + } + + @Override + public String toString() { + return value; + } + + @Override + public int compareTo(Variable o) { + return this.value.compareTo(o.value); + } + + +}