Table of Contents

Generators

A generator, as we use it, is a class that has a Next method that always gives you an object of a certain type. They work a bit like random generators, except the elements may or may not be random. They support various LINQ-like methods, and so also resemble sequences (although generators are always infinite). Generators are designed to be used for procedural content generation. All non-deterministic generators have overloads that take a seed, so you can use deterministic versions to ensure consistent results for different players if you need it.

There are a few “primitive” generators that you can construct directly with the various static methods in the Generator class. These include:

Generator Description
Constant A generator that always generates the same element.
Count A generator generates the sequence 0, 1, 2, 3, ..., n, 0, 1, 2, forever.
Repeat A generator that generates the elements of a given list repeatedly in sequence.
Iterate A generator that applies a given function to the last k elements to generate the next one.
OpenSawTooth A generator that generates evenly spaced numbers in a range, excluding the upper limit.
ClosedSawTooth A generator that generates evenly spaced floatsin a range, inccluding both limits.
FromFunc A generator that generates elements using a given function. Useful to get a generator from something that already behaves like a generator.

(There are Choose generators that are technically primitive but, since some of their overloads are not primitive, they are listed below)

There are also various random number and bool generators:

Generator Description
RandomBoolGenerator A generator that generates random booleans, given a probability of being true.
Poisson A generator that generates booleans so true occurs uniformly witin a specified range.
UniformRandomInt A generator that generates random integers uniformly distributed between 0 and a given number.
UniformRandomFloat A generator that generates random floats uniformly distributed between 0 and 1.
FrequencyRandomInt A generator that generates random integers with a given frequency distribution.
GaussianRandomFloat A generator that generates random floats with a Gaussian distribution.
MarkovRandomInt, MarkovRandomIntStartsWith A generator that generates random integers with a given Markov chain.
UniformVector2InRect A generator that generates random vectors uniformly distributed in a rectangle.
UniformVector2InCircle A generator that generates random vectors uniformly distributed in a circle.

There are several methods that manipulate and combine them to make more interesting generators.

Method Description
Where Generates only elements from a source generator that satisfy a predicate.
WhereWindow Generates only elements from a source geerator where the last n elements of the source satisfy a predicate.
Select Transforms the elements of a source generator and generates the transformed copies.
Cast Casts the elements of a source generator to a different type.
SelectMany Generates ele,ents from lists generated by the sources
Aggregate Uses a function to combine elements of a source generator generated so far into into a single element.
Sum Sums the elements of a source generator.
Average Averages the elements of a source generator.
Choose A generator that uses an integer generator to select from a list of objects or generators.
ChooseUniformRandom A generator that selects from a list of objects or generators with equal probability.
Group Groups elements of a source generator, and generates the groups.
Combine Uses several source generators to generate parameters for a function.
RepeatEach Uses a source generator, and repeats each generated element several times.
Interleave Interleaves elements of several source generators.
Pad Pads a source generator with a given element or list of elements.
Interpolate Generates elements by interpolating between elements a source generators.
InterpolateDither Generates elements by interpolating between elements a source generators, with dithering.
Iterate Generates elements by re-applying a function to one or more initial elements.
SwitchWhen Switches to a new generator when a condition is met.
SwitchAfter Switches to a new generator after a certain number of elements have been generated.

For a full list of all the generators and methods that can manipulate them, see Generator.

Here are some simple examples:

var generator = Generator
    .RamdomUniformInt(500)
    .Select(x => 2*x); //Generates random even numbers between 0 and 998

var generator = Generator
    .RandomUniformInt(1000)
    .Where(n => n % 2 == 0); //Same as above

var generator = Generator
    .Iterate(1, 1, (m, n) => m + n); //Fibonacci numbers

var generator = Generator
    .RandomUniformInt(2)
    .Select(n => 2*n - 1)
    .Aggregate((m, n) => m + n); //Random walk using steps of 1 or -1 one randomly

var generator = Generator
    .Iterate(0, Generator.RandomUniformInt(4), (m, n) => m + n - 1)
    .Where(n >= 0); //A random sequence that increases on average

In each case, elements are only being produced each time you call the Next method or one of its variants. Most calculations are done lazily, so the bulk of the processing is spread over getting the elements and most generators don’t required much memory.

To debug Generators, you can use the Log method to transform a generator into one that will log each element it generates.

There are also some other methods useful when working with generators:

Method Description
Apply Applies an action to the elements of a source generator.
Next<TSource>(IGenerator<TSource>, int) Gets the next n elements from a generator.
NextWhile Gets the next elements from a generator while a predicate is true.
Skip Skips the first n elements from a generator.
SkipAndTake Skips the first n elements from a generator and then takes the next m elements.
TakeAndSkip Takes the first n elements from a generator and then skips the next m elements.

Generators are useful in creating procedural content, or alter properties of game entities (such as their strength) procedurally. A place where you want to use randomness is the ideal candidate, especially when you want to inject some order to make the playable experience more interesting or coherent.

Here are some examples of what things generators can generate (taken from games we have built):

  • sky colors that change over time
  • scene decoration next to an infinite road
  • obstacle patterns
  • AI movement
  • game difficulty
  • random interesting paths
  • letters that have a good chance to make words