Generating Better Random Numbers


My current game – Riflestorm – has lots of procedurally generated levels, enemies, events and so on. Even a lot of the gameplay is random as well. This week I just wanted to share some tricks for generating more effective random numbers.

Basic Chance

// accuracy 0% - 100%
if (UnityEngine.Random.Range(0, 100) < accuracy) return true;

Common condition for basic attacks. Accuracy is the chance to land a successful hit.

Randomized Stores

local quantity = randInt(2, 3) -- 2 or 3
local price = randItem({400, 500}) -- 400 or 500
echo.store.sellSupplies(quantity, price)

randItem returns a random item from the given table (array). This is useful for limiting the randomness to a few options. In this case I don’t want random numbers between 400 - 500.

Critical Hits

public static int[] criticalBuckets = new int[]{115, 125, 135, 150};

public float BucketBonus(int[] bucket) {
    float bonus = 100.0f;

    if (bucket.Length > 0) {
        bonus = bucket[UnityEngine.Random.Range(0, bucket.Length)];
    }

    return (bonus / 100.0f);
}

// usage
float criticalBonus = BucketBonus(criticalBuckets); // 1.15f, 1.25f, 1.35f or 1.5f
weapDmg = (int)(weapDmg * criticalBonus);

A better way to handle critical hits is to create buckets with big stepped values for more varried results. This is used in many RPGs.

Random Damage

int splitDamage = (int)Mathf.Ceil(weapDmg * weapon.DamageSpray); // DamageSpray ~0.1-0.2

int damage = weapDmg - UnityEngine.Random.Range(0, splitDamage);

Slightly randomize damage output, for bigger numbers like the shotgun a bucket is used instead because it will give more varried random numbers.

Randomize List

local classes = randShuffle({"Class1", "Class2", "Class3", "Class4", "Class5", "Class6"})

Sometimes you want to randomize a list of something and loop through the results. For this case I created a randShuffle method to randomize the lists order.

Random Amount of Items From List

local rareItems = randAmount({"AK47", "M4Carbine", "L96A1", "SCARL", "Glock", "M9"}, randInt(2, 3)) -- {"AK47", "M9", maybe 3rd item}

I use randAmount to choose a number of items from an array and return it. Useful for choosing a smaller subset from a bigger pool, like in this case choosing which rare items to give.

Lastly Random Money

When a player wins a mission or gets money from an event. Instead of hard coding an amount. A simple 0 - 3 value is sent. The game will then calculate the correct amount to give.

eventUtil.randCash(randInt(2, 3)) -- give mid or highest amount of cash

Source

public int RandCash(CashLevels cashLevel) {
    int min = 0;

    switch (cashLevel) {
        case CashLevels.None:
            return 0;
        case CashLevels.Low:
            min = 1000;
            break;
        case CashLevels.Medium:
            min = 2000;
            break;
        case CashLevels.High:
            min = 2500;
            break;
    }

    min = (int)(min * diff.cashMod);
    int max = (int)(min * 1.25f);

    return Random.Range((int)(min / 10.0f), (int)(max / 10.0f)) * 10;
}

To keep money looking nice, all values below 10 is cutoff. All money is also multiplied by diff.cashMod to give more money in easy mode and less in hard mode.

Conclusion

I write a new blog post every week, subscribe to my newsletter for updates.

Related Posts

Test Your Chinese Using This Quiz

Using Sidekiq Iteration and Unique Jobs

Using Radicale with Gnome Calendar

Why I Regret Switching from Jekyll to Middleman for My Blog

Pick Random Item Based on Probability

Quickest Way to Incorporate in Ontario

Creating Chinese Study Decks

Image Magick Tricks

My Game Dev Process

Unit Manager Code Snippet