-1
\$\begingroup\$

Which of these two methods for creating a loot chance is easier to maintain and update?

  • The first method I'm thinking of uses an int going from 0 to 100000 (0,000 to 100,000).
  • The second is almost the same but using a float value going from 0.000f to 100.000f.

Both will pass to a Random.Next. If the value of the Random is less than the chance to drop value, the item will drop.

For efficiency and maintenance, is one preferred over the other?

\$\endgroup\$
6
  • 1
    \$\begingroup\$ Can more than one item drop from an enemy at once? \$\endgroup\$
    – Zibelas
    Commented Mar 4, 2021 at 14:18
  • 4
    \$\begingroup\$ "In question of efficiency" did you profile and you noticed there was a bottleneck when using one of them? \$\endgroup\$
    – Vaillancourt
    Commented Mar 4, 2021 at 14:19
  • \$\begingroup\$ @Zibelas - Yes it can. \$\endgroup\$ Commented Mar 4, 2021 at 14:20
  • 5
    \$\begingroup\$ You'll likely not have issues with efficiency here. Never. That's not where you should focus "effort toward efficiency". Focus on maintenance and ease of use by devs and content creators/designers. \$\endgroup\$
    – Vaillancourt
    Commented Mar 4, 2021 at 14:22
  • 1
    \$\begingroup\$ If one enemy can drop 25 items, do you want to roll for each item separately or can only the second item drop if the first one did not? Keep in mind that if you make the chance of the item to drop both 50%, the second item will only drop with a 25% since for it to drop the first one has to NOT drop. \$\endgroup\$
    – Zibelas
    Commented Mar 4, 2021 at 14:25

2 Answers 2

2
\$\begingroup\$

Personally I would pick int over float for the readability. You will never hit any performance issues with just creating and comparing an int or float.

My personal loot system would look similar to this, if multiple items can drop, you would roll multiple times

First you would do a roll what kind of rarity you hit. This adds up to 100%. (if 2 items can drop at once, means in ~ 1 out of 9 times you get no item all and once every 10.000 enemies you would get 2 orange items at once)

nothing(32) < gray(25) < green(25) < blue(15) < purple(2) < orange(1)

After that you would pull up the loot table of the monster. If you hit a group, you get with 100% chance the item from that group, now we determinate what item we get. Example for a gray group

  • sock with hole (1)
  • dried cheese (1)
  • useless rock (3)
  • rotten wood (3)
  • shiny piece of glass (2)

The numbers would mean how likely you get it. You can add them all together (in this case 10), roll a number from 1 to 10 and get the corresponding item. In % it would mean you have 10% for the sock or 30% chance for the rock in case you hit the gray reward box (that is an effective chance for the sock of 2.5%). But the great benefit of it is, you can just add as many items in a group as you want and dont need to care much about how many there are, you just have to determinate how much more likely one item is to drop compared to another. If they are all at 1, you get them all with the same chance.

If you have loot deminish system, you can still use the same system. You would populate a list once and remove one of the item chances afterwards. So if you get a rock, there would be still 2 left. But if you get the sock, before the drop gets refreshed, you can't get a second sock.

And last, if your drop can drop quest items and those are countable (collect 15 spider legs), let them always drop. Nothing is more frustrating than killing 100 wolves and still wonder why they are all blind and have no eyes for collecting.

\$\endgroup\$
4
\$\begingroup\$

We are talking C#, so I'll assume .NET. Thus you would either use System.Random.Next which works with integers, or System.Random.NextDouble which - as the name suggest - works with double. There no method in System.Random that uses float.


From System.Random it is preferible to use System.Random.NextDouble. This is how it works: first generate a pseudo random number between 0 and Int32.MaxValue (with uniform distribution), then convert it to double, and scale it down to the range between 0.0 and 1.0.

Contrast with System.Random.Next, which will do all those steps and then scale and shift the result to the requested range and cast back to int. If performance is your concern, then know that System.Random.Next has extra steps.

Thus, use System.Random.NextDouble and represent chances use values between 0.0 and 1.0. For example 25% is 0.25, which I'd argue is both easy to read and correct.


As per maintenance, declare a method that wraps whatever you choose to use (System.Random.NextDouble for example), and takes whatever is more convenient to you. Doing this, it is easier to replace System.Random with something else if the need arrives. In fact, you probably want the method to take a chance value and return bool.

As per representing the chance, both int and float are 32 bits, so no memory saved there… I'd say prefer a non-integer type, because your chances are not integer. There could, perhaps be a difference in performance if you are parsing the values from text, but unlikely to be relevant below the millions of values (profile if it is a concern).


Can System.Random be a bottle neck anyway? Yes. It happened to me while testing some voxel renderer and decided to simply pick each voxel at random (not what you want in practice), making each voxel a call to System.Random. Why did I do that? Because I didn't have any world generator code in place at the time, and wanted to test the renderer. It ran slow, and profiler pointed to System.Random. Reminder: use a profiler. So I replaced System.Random with a custom solution (which I suppose didn't have as good statistical properties - I never tested - but was faster and good enough that I didn't see patterns at a glance).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .