Skip to content

Instantly share code, notes, and snippets.

@anissen
Last active January 24, 2016 20:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anissen/d2e7736f118848d21aff to your computer and use it in GitHub Desktop.
Save anissen/d2e7736f118848d21aff to your computer and use it in GitHub Desktop.
Generative grammar for procedural generation
// Inspired by http://www.jorisdormans.nl/pdf/dormans2010_AdventuresInLevelDesign.pdf
enum Symbol {
Dungeon;
Obstacle;
}
enum Terminal {
Treasure;
Key;
Lock;
Room;
Monster;
}
enum Construct {
Symbol(s :Symbol);
Terminal(t :Terminal);
List(l :Array<Construct>);
}
class Rules {
var rules :Map<Symbol, Array<Construct>>;
public function new() {
rules = new Map();
}
public function add_rule(symbol :Symbol, construct :Construct) {
if (!rules.exists(symbol)) rules[symbol] = [];
rules[symbol].push(construct);
}
public function get_replacements(symbol :Symbol) :Array<Construct> {
return rules[symbol];
}
}
class Generator {
var rules :Rules;
public function new(rules :Rules) {
this.rules = rules;
}
public function generate(symbol :Symbol) :Array<Terminal> {
var replacements = rules.get_replacements(symbol);
var replacement = replacements[Math.floor(replacements.length * Math.random())];
return unwrap(replacement);
}
function unwrap(c :Construct) :Array<Terminal> {
return switch (c) {
case Terminal(t): [t];
case Symbol(s): generate(s);
case List(list): var ll = []; for (l in list) ll = ll.concat(unwrap(l)); return ll;
}
}
}
class Test {
static function main() {
/*
1. Dungeon => Obstacle + treasure
2. Obstacle => key + Obstacle + lock + Obstacle
3. Obstacle => monster + Obstacle
4. Obstacle => room
*/
var rules = new Rules();
rules.add_rule(Obstacle, Terminal(Room));
rules.add_rule(Obstacle, List([Terminal(Monster), Symbol(Obstacle)]));
rules.add_rule(Obstacle, List([Terminal(Key), Symbol(Obstacle), Terminal(Lock), Symbol(Obstacle)]));
rules.add_rule(Dungeon, List([Symbol(Obstacle), Terminal(Treasure)]));
var generator = new Generator(rules);
trace(generator.generate(Dungeon));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment