Random Number Distributions (JS)

Last week, I talked about a method for choosing random values within a set, one of the many uses for random numbers in a game. This time, I’ll go deeper into the notion of probability distributions, and how you can make use of them in game development and other kinds of programming. A word of warning: this post will have code (usually Javascript) and might use a lot of math!

Simply Random

The uniform distribution is the one you already know. It’s behind all the simple RNG functions we saw before, like C’s rand() or Javascript’s Math.random(), and it’s what you get when you roll a single die: every number has an equal chance of coming up. In math terms, if there are n possibilities, then the chance of getting any specific one is 1/n. Couldn’t be simpler, really. For most game uses, this is your main tool, and the “weighted set” from the other post is a handy add-on.

The Bell Curve

I mentioned the bell curve and the normal distribution last time, but here I’ll go into a little bit more detail. The bell curve, of course, is often an early introduction to the world of statistics and terms like “standard deviation”, and (as we saw in the other post) it’s what you start getting when you roll more and more dice at a time.

Obviously, that’s one way to get a normal distribution: roll a bunch of dice and add them together:

var dieRoll = function() { return Math.floor(Math.random() * 6) + 1; }
var bellCurveRoll = 0;
for (var i = 0; i < 10; i++) {
    bellCurveRoll += dieRoll();
}

This gives us something close (though not perfect): random numbers will range from 10 to 60, with 35 being the most common. If we need something better (i.e., more accurate), we’ll need to delve into probability theory. Don’t worry, it’s only a short dive.

Side Quest

The mean might be familiar to you, since it’s not much more than another name for “average”. For a normal distribution, the mean is the center point of the curve, the part where it’s at its highest.

Less familiar is the standard deviation, although you may remember that from high school or early college. It’s important in a lot of stats-based fields, because it measures how “clustered” a group of data points is.

Now, for a set of data, you can calculate the mean and standard deviation. That’s pretty much how things like grading curves work: you take the data and make a distribution that fits. For RNGs, however, we have to work backwards. Instead of calculating the mean and standard deviation for the data, we choose them at the start, and our RNG uses them to provide the proper distribution of values. For the normal distribution, this means that about 68% of the values will be within 1 standard deviation of the mean, 95% within 2, and 99.7% within 3. (By the way, the standard deviation is usually identified in math by the Greek letter sigma: σ. “3-sigma” confidence, then, is 99.7% likelihood that something is true. “Six sigma” encompasses everything within 6 standard deviations of the mean, or about 99.9999998%; it’s not quite “one in a billion”, but it’s pretty close.)

Back to Normal

So, knowing all this boring math, you can start getting your random numbers. Here’s one way of doing it in Javascript:

function normalDistribution (mu, sigma) {
    var u1 = Math.random();
    var u2 = Math.random();

    var z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(Math.PI*2 * u2);
    var z1 = Math.sqrt(-2.0 * Math.log(u1)) * Math.sin(Math.PI*2 * u2);

    return z0 * sigma + mu;
}

This uses a method called the Box-Muller transform to generate a random number on a bell curve. (The astute reader will notice that the function actually generates two random numbers, but throws one of them away. If you like, you can make a better function that stores the second value and returns it as the next random number.) The two parameters are our mean (mu, because it is often written as the Greek letter μ) and the standard deviation (sigma). The Wikipedia link above explains the theory behind this method, as well as giving links to other ways, some of which might be faster.

Exponential Randomness

Normal distributions have their uses, and they’re about as far as most people get in studying randomness. But we won’t stop there. We’ll move on.

Next up is the exponential distribution. This one isn’t that hard to make in code:

function expoDistribution (lambda) {
    return -Math.log(1.0 - Math.random()) / lambda;
}

But you might wonder if it’s really useful. Well, as it turns out, it does come in handy sometimes. Basically, the exponential distribution can be used anywhere you need a “time between events” type of randomness, like random events firing in a strategy game.

The lambda parameter is what’s called a “rate parameter”, and it’s intimately related to the mean; in fact, it’s the reciprocal: the exponential distribution’s mean is 1 / lambda. But what does it mean? Let’s take an example: say you’re making a game where special power-ups appear, on average, twice every minute. Using the above function with lambda as 2, the result would be the time (in minutes) until the next power-up. (The mean would then be 1/2, or 30 seconds, which makes intuitive sense.)

Pareto, Principle, and Power

If you’ve ever heard of the “Pareto Principle” or the “80-20 rule”, then you’ve got a head start on learning about the Pareto distribution. The general idea is thus: there are a few with a lot, and a lot with a little. “The top 20% control 80% of the wealth” is the most common way to state this particular idea, but a random distribution with these properties can be surprisingly useful in games. Here’s the code:

function paretoDistribution (minimum, alpha) {
    var u = 1.0 - Math.random();
    return minimum / Math.pow(u, 1.0 / alpha);
}

We have two parameters we can control this time. minimum is the lowest possible value that can be returned, while alpha controls the “shape” of the distribution. (Generally, higher values of alpha have a faster drop-off, meaning that lower values have higher probability. The “80-20” distribution has an alpha of log(5) / log(4), or about 1.161.)

The Pareto distribution isn’t just used for wealth, though. Anywhere you have a “long tail”, it might be what you’re looking for. Random city sizes (or star sizes, for an interstellar game) follow a Pareto distribution, and it might be a good way to model “loot drops” in an RPG; less powerful objects are far more common than the Ultimate Sword of Smiting, after all.

In Closing

These aren’t all that’s available, but the four distributions I’ve shown are probably the most useful for programmers, especially game developers. As before, I didn’t originally come up with any of this; it’s all been known since before I was born. Some code is converted from Python’s extensive random module, specifically the functions random.expovariate() and random.paretovariate(). The code for the normal distribution is my Javascript conversion of the Box-Muller transform example at the Wikipedia link above. (By the way, if you want me to post examples for a different language, just ask!)

A lot of people already know all this material, and there are plenty of other sites detailing them better than I can, but I hope that this is enough to get you interested.

Weighted Random Choices (JS)

In programming, we often need to generate random numbers, especially for games. Almost any game will use at least some kind of random number generator (RNG), and most need lots of them to drive the AI, make new levels, and so on.

Any programming language worth using (for games, anyway) will have some way of making an RNG. C has rand(), Javascript has Math.random(), and so on. Game engines usually add in their own ways, like Unity’s Random.value, constructed out of the base provided by whatever language they’re written in. All of these work in basically the same way: you ask the RNG for a value, and it gives you one. Usually, it’s a floating-point number between 0 and 1, which is good if that’s what you need.

Beginners starting out in game development quickly learn how to turn the float value from 0 to 1 (not so useful) into a number in the right range (more useful). The code for rolling a regular, six-sided die usually looks something like this (in Javascript):

var roll = Math.floor(Math.random() * 6) + 1;

It’s a pretty standard technique, and many languages and game engines now have functions that do this for you. And, again, if that’s what you need, then it’s perfect. Sometimes, though, it’s not what you need. This post is for one of those times. Specifically, the case where you need to choose one value from a list.

Simple Choices

When you simply need to pick a single value out of a list (array, vector, whatever), that’s easy. All you’re really doing is the same thing as rolling a die:

var index = Math.floor(Math.random() * array.length);
var choice = array[index];

In effect, we’re choosing a random array index. Easy. Like rolling a die, it gives you an equal chance for each possible value. (If your array contains the numbers from 1 to 6, then you’ve just created a less efficient method of rolling a die.)

Harder Choices

Not everything has an equal probability, though. (Statistics as a science wouldn’t exist if it did. Whether that’s a good or bad thing depends on the way you look at it, I guess.)

Some things can be approximated with the die-rolling method above. Lotteries, for example, work the same way, as do raffles. For some games, that may be all you really need. But other games require more from their RNGs than this.

Take the case of rolling multiple dice. Anybody who has played a role-playing game, or craps in a casino, or even Monopoly knows that, while every number on a die has an equal chance of popping up, things get more complicated when you add more dice. With two dice, for example, a total of 7 is more common than a 2 or 12, because there are more ways to roll numbers that add up to 7: 1+6, 6+1, 2+5, 5+2, 3+4, and 4+3. Add more dice, and the numbers get bigger, the range gets wider, but the idea stays the same: numbers “in the middle” are more likely than those on the outside. (Due to what’s called the central limit theorem, the more dice you roll, the more the graph of possible outcomes starts to resemble a bell curve.)

Rolling a lot of dice is impractical, even on a computer. The probabilities aren’t always so nice and neat that a bell curve works. Maybe you need to choose from a set where the ends are more common than the middle, or a list with a weird distribution of frequencies like the letters in English text. (One out of every eight letters, on average, is E, but Z is over a hundred times less common.) A word game, for instance, would certainly need to do something like this.

Now, there are plenty of different ways of generating random numbers based on frequencies. Here, I’m only going to describe what I think is the simplest. First, we need a problem. Let’s say you’re making a word game that, for whatever reason, uses the letter tiles from Scrabble. (You probably wouldn’t be making an actual Scrabble game, because some people or lawyers might not like that, but we’ll say you’re using the letter frequencies.) Looking at that link, you can probably see that just using random choices won’t help you. We need something different.

First things first, let’s define the set we’re choosing from (note the space at the end, which represents the blank tiles):

var letters = ['a','b','c','d','e','f','g','h',
    'i','j','k','l','m','n','o','p','q','r','s',
    't','u','v','w','x','y','z',' '];

Since this is an uneven distribution, we need some way of representing each probability. In this method, we do this by “weighting” each value. We’ll store these weights in their own array:

var weights = [9, 2, 2, 4, 12, 2, 3, 2,
    9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4,
    6, 4, 2, 2, 1, 2, 1, 2];

In this case, the sum of all the weights is 102 (100 letters, 2 blanks). Therefore, the ratio of each weight to that sum is the frequency of the letter. (For example, there are 12 E tiles, so E’s frequency is 12/102, or about 11.8%.) That’s the key to this method. Basically, we do something like this:

function randomLetter() {
    var totalWeight = 0;

    for (var w in weights) {
        totalWeight += w;
    }

    var random = Math.floor(Math.random() * totalWeight);

    for (var i = 0; i < letters.length; i++) {
        random -= weights[i];

        if (random < 0) {
            return letters[i];
        }
    }
}

(Obviously, in a real game, we’d need something much more robust, with better error handling, etc., but this is enough to illustrate the point. Also, this isn’t normally how I’d write this function, but I’ve simplified for the same reason.)

The function works by picking a random number from 0 up to the sum of the weights. We then use that as an “index”, but not directly into the array. Instead, we count down from our chosen number, each time subtracting successive weights, until we go below zero, where we produce the corresponding letter.

Let’s say that our random number is 15. We go through the weights array, starting with 9. Subtracting 9 from 15 leaves 6, so we keep going, down by 2 to 4, then by 2 again to 2, then by 4 down to -2. That’s below zero, so that’s where we stop, returning 'd'.

This method isn’t just limited to choosing letters. You can use it anywhere you need a biased sample. Think of a game that has five different types of enemies, each with different chances of spawning. Set up a list of enemy types, another holding their appearance frequencies, and the same method will give you waves of bad guys.

(Note: I’m not claiming credit for any of this. It was all figured out a long time ago, and certainly not by me. I’m not even the first to write about it online. But it’s definitely something beginners should learn, and I hope to post more little “tutorial” articles like this in the coming months, because we were all young, once.)

Elan – Unicode and Emoji in your code

Everyone knows about Unicode. A massive set of thousands of characters, all ready to be used everywhere. Except in code. Sure, many programming languages allow accented letters (for example) in their names, and most support Unicode in comments or strings. But there are very few that harness the full power of the Universal Character Set. Most text editors are Unicode-aware, but we’re still forced to write :<= instead of .

On the other side of the coin, the younger generation has fully embraced Unicode, whether they realize it or not. The latest revision of the Unicode standard added a number of “emoji”, emoticons and pictographs that are popular in messaging apps and elsewhere. With just a few symbols, emoji can convey a large amount of information, such as moods and activities. It’s even possible to write a story using only emoji. But you can’t write code with them.

Until now.

Introducing Elan

Elan (Emoji LANguage) is a new programming language I have created to merge these two disparate worlds. In Elan, almost every Unicode character, from emoji to Greek letters to Chinese ideographs to musical notes are usable. Every operation in the language can be shown with symbols, in addition to text. This functionality can give our code the same expressive power available to our smartphones. No longer do we have to be limited to ASCII. With Elan, the whole world is open to you.

In the rest of this post, I’ll give a brief description and tutorial on Elan. It’s always in development, though, and new features are on the horizon. The latest code is available at this Github repo, and I’ve also put up a live compiler.

A word about character support

I understand that not all systems, keyboards, and editors have support for entering the full range of Unicode characters. To help those unfortunate programmers that must use such hardware and software, Elan has an alternative input facility. Each symbol that can’t be typed on a US keyboard has an alternate form consisting of either a valid symbol or a few letters surrounded by colons. For example, the assignment operator ⬅ can also be written as :=:. The live compiler page lists all the symbols currently used in Elan with their corresponding alternates.

Variables

Variables are just names attached to values. In Elan, a name be a string of letters and numbers from any language, as long as you start with a letter. But Elan also allows single symbols as variable identifiers. (Specifically, they have to be symbols from outside the Basic Multilingual Plane of Unicode, but this is a current limitation of the compiler.)

This means that you can have variables named any of the following:
xyz ALongVariableNameWithMixedCase élan π こんにちわ 🌈

Variables can be assigned values. In many languages, this uses the equals sign (=), which causes confusion. With Elan’s support for Unicode, we can use ⬅ instead:

x ⬅ 1; twox ⬅ x * 2; こんにちわ ⬅ "hello"; TheAnswer ⬅ 42

As you can see, semicolons can be used to separate statements, but newlines work just as well.

Operators

Every language needs a set of operators. Elan includes the following:

  • The assignment operator ⬅, which you just saw.
  • The usual arithmetic operators: + - * / for addition, subtraction, multiplication, and division. The minus sign can also be used for negative numbers.
  • The modulo operator %, similar to many other languages. (This may get an alternate symbol in a later version.)
  • The power operator ^, that raises one value to the power of another. (e.g., 3^3 = 27)
  • Comparison operators < > = ≤ ≥ ≠. Note that, because we don’t use the equals sign for assignment, we can use it for comparison, just like in math class. (If you can’t type the “or equal” symbols, you can also use <= >= /=.)
  • Logical AND and OR, as & and |. (Logical NOT is an oversight that I’ll fix in a future version.)
  • Increment and decrement operators, ⬆ (:++:) and ⬇ (:–:), that take a variable and either add 1 or subtract 1.
  • A lot more that I’ll show you in the sections below.

Expressions can be as complicated as you need them to be. The order of operations should be familiar if you’ve used any other programming language, with multiplication coming before addition, etc. You can also use parentheses to make your intent clear.

Types of Values

Elan doesn’t have a static type system like Java or C++. But it does have the notion of different kinds of values: numbers, strings, booleans, lists, functions, objects, and null. Most of these should be obvious: numbers are numbers, strings are text inside quotes. Booleans can be either true (✔ or :t:) or false (✖ or :f:). Lists are like arrays in other languages, with multiple values accessed by number, while objects have values that are accessed by name. Functions are blocks of code that you can call. Null (🚫 or :null:) is simply the absence of a value.

Examples of values:

  • Numbers: 1 42 0.5 -17
  • Strings: "c" "string with spaces" "512"
  • Lists: {1,2,3} {"a","b"} {}
  • Booleans: :f: ✔
  • Null: 🚫

Functions and objects will be discussed below.

Conditional Expressions and Statements

The conditional expression is similar to other languages’ ternary operators. Given a condition and two options, it returns the first option if the condition is true, the second if it is false. The general format of a conditional is:

condition ? true-expression ! false-expression !

For example, x < 10 ? "less" : "more" produces the string "less" if x is less than 10, otherwise it is "more". (Of course, this doesn't handle the case where x equals 10, but that's for another time.)

If you don't need the "else" portion of the conditional, it still has to be present, but you can leave it blank: x < 0 ? x ⬅ 0!!.

A conditional statement is slightly different. It doesn't produce a value, so you can't assign it to a variable, but it can include multiple statements, including any of those shown below, such as loops or function definitions.

Functions

Functions allow us to do things. As such, they are an important part of Elan. To define a function, you use the ✏ (:def:) symbol. To its left are the parameters of the function, written as a list. To the right is a block of statements ended by the ◀ (:end:) symbol. You can have an empty parameter list with {}, but the body of the function must have at least one statement.

Inside the function, you can return a value by writing that value followed by the ↩ (:return:) symbol. (To return a boolean value, you can instead use the shortcut symbols 👍 (:yes:) and 👎 (:no:) for true and false.)

How you call a function depends on if it requires parameters. For a function that doesn't, you can use the :call: symbol, which you can write as either 📞 or 📱. To pass parameters to a function, you first use the ✉ (:with:) symbol with a list of parameters, then call the function as before. For example, 📞 f and ✉ {a,b} 📱 g.

Examples of functions include:

  • {n} ✏ n*2 ↩ ◀, which doubles any number passed to it.
  • {s} ✏ s.length ≥ 1 ? 👍 ! 👎 ! ◀, which returns true if a string is not empty.
  • {x,y} ✏ ✉ {(x^2 + y^2)} 📞 Math.sqrt ↩ ◀, the Pythagorean function.

By themselves functions you define have no names, but they can be assigned to variables to give them names. Doing this obviously allows you to call your own functions, and it also enables recursion, as in the classic Fibonacci function:

fib ⬅ {n} ✏ n < 2 ? 1 ↩ ! ✉ {n-1} 📞 fib + ✉ {n-2} 📞 fib ↩ ! ◀

Iteration and Loops

Elan has two kinds of looping. The first is iteration, which goes through a list and executes a block of code for each value in the list. (This is like a for loop in other languages.) For this, we can use the 🔁 (:iter:) symbol. On the left goes the list, which can also be a variable holding a list, while the code block goes to the right. Like with functions, the code block ends at the ◀ symbol. Inside the block, you'll most likely need the current value, and this can be obtained with the :i: symbol, which can be written as any of ☝, 👆, or 👇.

Examples:

  • {1,2,3,4,5} 🔁 ✉ {☝^2} 👍 console.log ◀ prints the squares of the numbers 1 to 5 in order.
  • values ✉ {☝} 👍 someFunction ◀ calls someFunction with each value in the values list. (This pattern is so common that it might get its own shortcut symbol in a future version.

Instead of iterating through a list, you can also set up a loop that will run until a condition is met, or until you specifically tell it to stop. These loops (called while loops in many languages) are defined by the :loop: symbol, either 🔀 or 🔃. This symbol is followed by the block to execute each time through the loop, and it can be preceded by a condition that will stop the loop.

Inside the loop, you can use the ◼ (:stop:) symbol to "break out of" the loop, ending it immediately. (This is the only way to stop a loop without a condition.) Also, the ⏩ (:ff: or :continue:) symbol skips the rest of the block, returning to the beginning of the loop.

For example, x ⬅ 1; x < 1000 🔀 ✉ {x} 👍 f; x ⬅ x*2 ◀ passes successive powers of 2 to the function f, stopping once it reaches 1000.

Choices

For choosing one path of code from among many, Elan has the choice statement, similar to other languages' switch. The general format of the choice statement is:

test-expression :switch: default-block :case: choice-1 :do: code-block :case: choice-2 :do: code-block etc.

The :switch: symbol can be written as 💡, while :case: can be either ☑ or 🔘.

Example: {x} ✏ x 💡 "many" ↩ ◀ ☑ 1 ➡ "one" ↩ ◀ ☑ 2 ➡ "two" ↩ ◀ ◀ defines a function that returns a word based on its parameter. The number 1 becomes "one", 2 becomes "two", and any other number returns the value "many".

Objects and Lists

Objects in the current version of Elan function in the same way as their Javascript equivalents. You create an object by using the :object: symbol, written as either ☺ or 📦. This is followed by a block containing assignments. Each assignment defines a property of the object.

Example: o ⬅ ☺ x ⬅ 42 ◀ creates a variable o which is an object. This object has a single property called x, which is set to 42.

(Note: In the current version of Elan, lists are essentially just objects whose properties are consecutive integers starting from 0. In other words, a list like {"a","b","c"} can be considered an object with properties 0, 1, and 2.)

You can access the properties of an object in one of two ways. First, the dot (.) works just like in Javascript, meaning that o.x on the above object will give us the value 42. The underscore (_) does exactly the same thing, but it is set to a much lower precedence, allowing you to use an expression like a_b-1.

New objects can be created with the 🔨 (:new:) symbol, which, at the moment, works just like the Javascript new. Example: a ⬅ 🔨 Array.

Error Handling

Currently, errors are handled using something like Javascript's exception handlers.

The general form for handling errors is:
:try: attempted-statements :catch: error-variable error-handler

The :try: symbol can be 🔍 or 🔎, while :catch: is ✋. If an error occurs in the "try" block, then the "catch" block will be executed. The error variable is set when the error happens, and it is only used for the catch block.

You can throw errors from your own with the :throw: symbol, written as ⚾, 💣, or 💩. It is followed by an expression that will be passed as the error variable to any block that catches it. Example: 💩 "Something went wrong".

Conclusion

There are a lot more things that a language probably should do, but Elan is complete enough that you can play with it, tinker with it. I have plenty more ideas, but it's best to start small.

I hope you like what you've seen. If you have any comments, bug reports, or feature requests, leave them here or at the Github repo.

Have fun! 😎