mardi 16 août 2022

Weighted random number generation with seed and modifiers

I try to implement a generation of a complex object based on a weighted elements list.

ListEnum.kt

enum class Elements(weighting:Int){
    ELEM1(15),
    ELEM2(20),
    ELEM3(7),
    ELEM4(18)

// function to get weighted random element
companion object{
        fun getRandomElement(seed:Long): Elements{
            var totalSum = 0
            values().forEach {
                totalSum += it.weighting
            }
            val index = Random(seed).nextInt(totalSum)
            var sum = 0
            var i = 0
            while (sum < index) {
                sum += values()[i++].weighting
            }
            return values()[max(0, i - 1)]
        }
    }
}

MyClass.kt

class MyClass{

    fun getRandomElement():RandomElement{
        val seed = Random.nextLong()
        val element = Elements.getRandomElement(seed)
        return RandomElement(element, seed)
    }
}

I can persist the seed and recreate the same object with the same seed.

Now I want to modify the weighting in the Elements enum at runtime.

Elements.kt

enum class Elements(weighting:Int){
    ELEM1(15),
    ELEM2(20),
    ELEM3(7),
    ELEM4(18)

// function to get weighted random element
companion object{
        fun getRandomElement(seed:Long, modifiers:Mods): Elements{
            var totalSum = 0
            values().forEach {
                var modifiedWeighting =it.weighting
                if(modifiers.modifier[it] != null){
                    modifiedWeighting= modifiers.modifier[it].times(modifiedWeighting).toInt()
                }
                totalSum += modifiedWeighting
            }
            val index = Random(seed).nextInt(totalSum)
            var sum = 0
            var i = 0
            while (sum < index) {
                var newSum = values()[i].weighting
                if(modifiers.modifier[values()[i]] != null){
                    newSum = newSum.times(modifiers.modifier[values()[i]]).toInt()
                }
                sum += newSum
                i++
            }
            return values()[max(0, i - 1)]
        }
    }
}

That works for generating random elements with modified weightings, but now I can't recreate the object because the seed does not consider the modifiers.

How can I generate such an object based on modified weightings that I can recreate just from the seed?




Aucun commentaire:

Enregistrer un commentaire