Need help from a fellow programmer

  • The masquerade of murder returns! A new game of Vampires Amongst Us has begun. Unmask the killers, trust no one, and try to survive the night. Find out more and sign up now!

unixknight

Zombie
May 22, 2008
4
Wshington, DC
Zombies
4
So I wanted to be able to determine configurations and loadouts for my units and experiment with different enemies, so I wrote a program to simulate hand to hand fights between units in Warhammer.

Alright so my program is pretty much done, but there seems to be a problem with the random number generator I'm using in my code. I've thoroughly checked the program and can find no logic errors, yet when I run the following simulation:

Bretonnian MAAs vs. VC Skeletons

The Bretonnians will refuse to charge (fail leadership) 70% of the time when the Skeletons are wielding spears and 85% of the time when the Skeletons have a hand weapon...

And yet the Leadership test has nothing whatsoever to do with the defending unit's weapon choice...

I think what's happening is the cheesy random number generator that comes with .NET is somehow being influenced by this. Either that, or somehow I'm missing something in code.

Anybody have any ideas on where I can get a decent randomizer?
 
Sure. This is the function I'm calling in my Dice class from my program. (This is in VB.NET) The Dice object has already been initialized as 2d6 for rolling Leadership. (number is a Global variable set to the number of dice, sides is Global and set to the number of sides on the dice)

Public Function Roll() As Integer
Dim total As Integer
Dim i As Integer
Static RandomNumGen As New System.Random

total = 0

For i = 1 To number
total = total + RandomNumGen.Next(1, sides + 1)
Next

Roll = total
End Function
 
As long as sides = 6 and number = 2, it should be ok...

Why are you declaring RandomNumGen as static when you're recreating it (and reseeding it) every time into the function?

The function looks fine. It's not granular, but it should work. One thing I don't understand is why you wouldn't pass 'number' and 'sides' in as parameters. A global 'number' can change, especially if there's any threading going on.

Perhaps code elsewhere is faulty?

The other thing is, is that if you leave out a seed value, .Net uses current date and time. If your computer is fast enough, the numbers will not be truly random. To test, you could have a Thread.Wait(10) (or is it sleep?) or something like that.
 
Hmmm good question about the Static... I think it's because when I originally designed the class, I was going to make it a static set of dice but that later became unnecessary and I forgot to remove it.

That function is overloaded and can take the number and sides as parameters. In this case, the dice object was already created an initialized so there was no need to keep passing those parameters. There's no multithreading in this case.

Good point about the seed value... I think I'll put a wait in for a millisecond or two to see if it makes any difference.
 
Ok so I've done the following:

Seeded the random number generator with a fixed Int value and
Let it default seed form the system clock but added a 5ms sleep for the thread after each time.

I'm still getting pretty consistent results at 72% charge failure vs. 84% over 10,000 battles.

This is really bizarre.
 
Just use an output of numbers from your function. I don't think the function is faulty. Run this and only this function a number of times, and having the output/logging done in the function itself.

You seeded the random number generator iwth a fixed number...? That will generate the same values every time.

Do you want to zip/rar your program and send it so I can take a look at what you're doing?
 
Alright so predictably, when I put in a fixed seed value it gave me 100% charger wins results. (When I tried that before I did it in the wrong function in my Dice class...)

So when I went back and set a Thread.Sleep(1) in the correct function (gawd)

I now have consistent 79% failure to charge results in both cases of defender weapons.

So it would seem that this pseudo random number generator blows (we knew that) and that the temporary fix is to cripple the program's performance by making it pause for a millisecond every time it rolls dice, which could happen several dozen times in each battle, and I like to run at least a thousand to get a decent statistical average.

So I am still on the lookout for a nicer randomizer to put in my Dice class, but at least this eliminates the rest of the code as being the source of the problem.
 
All random number generators come from an algorithm and are therefore pseudo random. The correct approach would be to use random seed numbers(that's the only way to make it truly random) but there lies the problem; where are you going to get truly random seed numbers? You could have two random numbers, and use the first to do a .Next x where x ist he number from the first one.

What is your program doing, and are you willing to share your source code? (I've wanted to build something for awhile but time restraints prevent this).
 
Sleep(1) will not cripple performance much. Run 10 000 times, it will result in a 10 second delay. I do not think for this applications purpose it would be considered crippled, just slower.

There are other randomizer classes out there that use different algorithms. YOu could leverage the crytography classes to do it, I believe they have a stronger randomizer in them.

The other thing you could do is seed the randomizer dice rolling object with a randomly generated number. Every time you run the program you'll have a different 'seed' to seed the other randomization functions.

So in the main() function, generate a global 'seed' value (as big of range as possible, I think it just has to be a 32 bit integer value) and feed this seed into all the other Randomizer functions. Keep the rest of the randomizers static (so you're not reseeding them with the same number), and just seed it once in the creation event. That will clear up the performance issue and should give you random numbers.
 
That's the thing... as written now it IS crippling because it doesn't just roll the dice 1 time for each battle. It's a couple dozen... so if you consider 24 die rolls x 10,000 x 1ms you get serious delays for each simulation.

I've got code for a much better randomizer and I"m going to work it into the dice class, then redesign the class so that it isn't instantiating a new randomizer for each die roll. That should improve the quality of the random numbers and improve performance.
 
As I said, generate a random seed for the randomizer class, and generate the seed(s) on startup. Have a global randomizer, and get your numbers from it.
 

About us

  • Our community has been around for many years and pride ourselves on offering unbiased, critical discussion among people of all different backgrounds. We are working every day to make sure our community is one of the best.

Quick Navigation

User Menu