public int[] _choices;
private void Pick()
{
int choiceIndex = GetRandomChoiceIndex(_choices.ToArray());
float valueToRemove = _choices[choiceIndex] / _choices.Length - 1;
float valueToAdd = valueToRemove / _choices.Length - 1;
Debug.Log($"Chosen Index: {choiceIndex} , Value: {_choices[choiceIndex]}, Value To Remove: {valueToRemove}, Value To Add: {valueToAdd}");
_choices[choiceIndex] -= Mathf.RoundToInt(valueToRemove);
for (int i = 0; i < _choices.Length; i++)
{
if (i != choiceIndex)
{
_choices[i] += Mathf.RoundToInt(valueToAdd);
}
}
}
private int GetRandomChoiceIndex(int[] weights)
{
int randomWeight = Random.Range(0, weights.Sum());
Debug.Log($"Random Weight Is {randomWeight}");
for (int i = 0; i < weights.Length; ++i)
{
randomWeight -= weights[i];
if (randomWeight <= 0)
{
return i;
}
}
Debug.LogError("Could not retrieve Random value");
return -1; // Something went wrong
}
When one choice is chosen, the probably if it being chosen again is decreased and the others are increased.
With this script, I’m running into some problems:
- The values can sometimes go below 0
- The values being drastically different than their original values I.e. originally 20,17 turns into 3,4.
- Not sure if it’s working properly at all.
Ah, the beauty of “just make it random!”
“Well, what do you mean?”
https://www.youtube.com/watch?v=DqL9R5PqE20
Sounds like you got a bug billygamesinc… time to start debugging!
But first I would define the behavior you want, because already your message title (“making them less likely”) implies that it is NOT a truly random thing.
By debugging you can find out exactly what your program is doing so you can fix it.
Use the above techniques to get the information you need in order to reason about what the problem is.
You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.
Once you understand what the problem is, you may begin to reason about a solution to the problem.
This is where you write some code to run some tests for you. Doesn’t have to be a full on Unit test, but you can still write some editor code to run this code a bunch of times and spit out the results in whatever format you wish to view it in.
Otherwise you’re not really asking a question in this thread. You’ve just posted some code and listed your issues with it. What do you want us to do?
Well, this is most likely not what you want- You divide by the length of the choices array and then you subtract 1 from the result. First of all you’re doing an integer division here. That means a single item could hit a minimum which is essentially twice the number of elements. So if you have say 50 elements in the array, any weight that is 99 or less will never subtract anything because 99/50 - 1== 0. Since you work with integers all along, it also means you probably never actually add anything to the weight of other elements since you essentially divide by your number of elements cubed. So the “valueToRemove” has to be 100 or greater in order to cause any addition to the other elements.
Furthermore, even when you would use floats instead of ints everywhere, “adding” weight is almost always wrong. If you have a weight of 1000 and you add one, you upped the chance to 1001 which is 0.1% increase, However if some other element have a weight of 1, adding one means it now has a weight of 2 which is a 100% increase in the chance.
Such things usually are done with floats because you can not properly express fractional changes. Since you currently generally subtract more than you add, over time the weight values would all drop to the minimum eventually.
So just simple static analysis already shows that this is not a very viable approach. Changing the actual weights also has several issues. You would need to store those changed weight tables in a save game and this would make it almost impossible to update the game to a newer version where new items would be introduced. Such “changes” to the weights should be tracked separately, probably as delta values or as factors for the original weight / chance. Though unless your system is perfectly balanced, the slightest error could mess up your chances. When using an additional factor array for each value, the sum of all factors (which would be 1.0 in the beginning) should always equal the number of elements so it stays balanced. With a factor array you can even do a “normalization” if it would drift away.
Though you should ask yourself, if that’s really what you want. Such systems allow players to game the system as it’s not random anymore (like explained in the video Kurt posted).
When working with weights, it’s usually not necessary to increase the other weights when you decrease the one currently picked as decreasing the current weight, automatically would increase the others.