How would I make an infinite mine generation with randomized ores with certain rarity?

I’ve been trying to work on a system for my game in which you mine and random ores appear as you mine down, how would you suggest me making a system which does that in the first place where I can adjust the following:

Rarity
Max Depth
Min Depth
Interchangeable rarity based off of events

1 Like

Don’t bother with percentage-based rarity, use a weight system instead. So instead of dirt=90%, gold=10%, do dirt=9.0, gold=1.0. It’s like the opposite of rarity though, I can’t think of a better word than “abundance”. “Frequence” would make sense but it’s too similar to another term used in this kind of proc gen so nah.

You’ll want a table of block information. I’d use a ModuleScript and call it “BlockInfos”, and make it something like this:

local BlockInfos = {
    [1] = {Id = 1, Name = "Dirt", Model = game.Repli...., MinDepth = 0, MaxDepth = 1000, Abundance= function(pos) return 0.9 * math.random() end},
    [2] = {Id = 2, Name = "Gold", Model = ..., Min..., Abundance= function(pos) return 0.1 * math.random() end,
    ...
}

that way any script that needs to know about the different block types can require it and you only have the information in a single place.

Abundance is a function of where the block is located in 3D, because having a single weight number doesn’t give you any flexibility to do level design (e.g. dirt is only common near the top). To actually determine what block to place at a point, sample every block type’s abundance function at that point and place the one with the highest. You could make a simpler system where only the height (y coordinate) has any effect, but you have many more options if you use all 3 coordinates. Plus it enables you to use a 3d noise function to determine where ores occur, which you can use to make more natural-ish levels. E.g. instead of just single blocks of each ore occurring here and there, they can kind of generate in “clumps”.

It could look something like

--This is the actual important part, the rest is just boilerplate.
function getBlockTypeAt(point: Vector3)
    local depth = -point.Y --I'd use height, MinHeight and MaxHeight instead, tbh, to avoid the negation. Up to you.
    local blockInfosAtDepth = filterBy(BlockInfos, function(bi) return depth == math.clamp(depth, bi.MinDepth, bi.MaxDepth) end)
    return maxBy(blockInfosAtDepth, function(bi) return bi.Abundance(point) end)
end

--Helper functions
function maxBy(items, selector)
    local maxItem, maxValue = nil, math.huge
    for _, item in ipairs(items) do
        local value = selector(item)
        if value > maxValue then
            maxValue = value
            maxItem = item   
        end
    end
    return maxItem
end

function filterBy(items, selector)
    local filtered = {}
    for _, item in ipairs(items) do
        if selector(item) then
            table.insert(filtered, item)
        end
    end
    return filtered
end

Here’s how you could make abundance functions for dirt and stone, where it’s mostly dirt near the top and mostly stone further down:

local SEED = math.random(10e7)
local R = Random.new(SEED)

    [1] = {Name = "Dirt", ..., Abundance = function(pos) return 5 - pos.Y / 10 + R:NextNumber(0, 10)  end},
    [2] = {Name = "Stone", ..., Abundance = function(pos) return pos.Y / 10 + R:NextNumber(0, 10) end},

If you want the “clump” behavior you should sample math.noise and use that instead of (or in addition to) the pure RNG. You can analyze your abundance functions by graphing them:

You can see one line starts bigger but then becomes smaller, so the X value where they cross is the depth at which they’re equally abundant and then one dominates on either side of that point. Hope that makes sense :sweat_smile:

Do you mean for like a Christmas event, e.g. candy cane blocks that only appear during December or w/e? You could modify the rarity functions to achieve that. Just have an if statement that checks the date. You can use this to make anything in the game affect level generation, like maybe a player purchases a dev product that makes dirt less common and valuable ores more common.


Hope this helps, ask away if you have any questions

2 Likes