Random Numbers not working?

mikeejimbo

Chieftain
Joined
Jan 16, 2010
Messages
65
Most likely I'm just using them wrong.

I have this line:

Code:
if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SLAVEMAKER')) and not bAnimal and (self.getRandomNumber(1) == 1):

But it never runs the code below it. Now I realize that, given that I have given a chance for it to run or not, there is a finite possibility that I have just never seen it. However, after many trials, I have never seen it run. Yet, if I take out the last condition, to make it:

Code:
if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SLAVEMAKER')) and not bAnimal:

It does work.
 
Most likely I'm just using them wrong.

I have this line:

Code:
if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SLAVEMAKER')) and not bAnimal and (self.getRandomNumber(1) == 1):
But it never runs the code below it. Now I realize that, given that I have given a chance for it to run or not, there is a finite possibility that I have just never seen it. However, after many trials, I have never seen it run. Yet, if I take out the last condition, to make it:

Code:
if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SLAVEMAKER')) and not bAnimal:
It does work.

Civilization has it's own random number generatior, called CyGame().getSorenRandNum(100, "Bob"). It takes two arguments, the top number to be generated, and a string. As for the string, I have no idea why it's nessecary, as it has no effect whatsoever on the generation of the number that I know of. It's more a reference to the modder what it's being used for. The name of the function, particularly the name SOREN, is a reference the lead programmer, Soren Johnson. His name is also on the watch that appears when you enter the modern era, but I digress...
 
if you use CyGame().getSorenRandNum(100, "Whatever") it will returns values between 0 and 99
 
Thanks! I've seen getRandomNumber() used in other places, but I'll use getSorenRandNum() and see if that does it.
 
Your key problem is that any random number function which takes N as an argument returns an int between 0 and N-1. So the code is behaving correctly, it is returning a random number between 0 and 0. Your comparison to 1 will never pass.

I recommend "if your_random_function(100) < 50". Some people say that the least significant bit of most random number generators is "less random". I don't know if that is true, but it is fairly easy for most people to read that line as a 50% chance of whatever happening.

BTW, the string in the Soren function there is written into the MP log file. It is critical to have different, useful strings there if you ever expect your mod to be played MP. Nobody wants OOS errors, but if you have one, the log file will list all the random numbers generated. It is very common to discover that one player's game takes a certain branch while the other player's game does not, and the random number trace is useful for this.
 
Your key problem is that any random number function which takes N as an argument returns an int between 0 and N-1. So the code is behaving correctly, it is returning a random number between 0 and 0. Your comparison to 1 will never pass.

That would be a problem. I was under the impression that it generated a number between 0 and N.

However, I have changed which N I used before, and it still wasn't working.
 
Post the updated code so we can verify that you made the correct changes.

Actually, it is in fact still not quite working. Here is what I have:

Code:
                iNumber = CyGame().getSorenRandNum(10, "Chance")
		iTestNumber = 1
		
		if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SLAVER')):
			iTestNumber = 2
		
		if unitLoser == gc.getInfoTypeForString('UNIT_WOLF') or unitLoser == gc.getInfoTypeForString('UNIT_PANTHER') or unitLoser == gc.getInfoTypeForString('UNIT_LION') or unitLoser == gc.getInfoTypeForString('UNIT_BEAR'):
			bAnimal = True
		
		if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SLAVEMAKER')) and not bAnimal and iNumber < iTestNumber:

See, here's what it's supposed to do: A unit has a promotion called Slavemaker, that, when it defeats a non-animal unit, there is a chance it will create a worker. Then there is another promotion called Slavemaker II (Or PROMOTION_SLAVER - only the description is Slavemaker II, everywhere else I call it PROMOTION_SLAVER. I'll make this consistent later, I promise.)

Now, when I take out the "and iNumber < iTestNumber" condition, it does work, and spawns the worker, so I have left out that actual code. (Which you could easily guess anyway, it's pretty simple.) Additionally, when I make it "iNumber < 1", it works (which should give it a 10% chance to capture a worker, and in testing it worked out to approximately this ratio).

Also, I realize that starting my integers with i, pointers with p and booleans with b is merely a convention, but do you think it's one I should continue with? I noticed that it's done this way in most of the Civ files.
 
Actually, it is in fact still not quite working. Here is what I have:... Now, when I take out the "and iNumber < iTestNumber" condition, it does work, and spawns the worker, so I have left out that actual code. (Which you could easily guess anyway, it's pretty simple.) Additionally, when I make it "iNumber < 1", it works (which should give it a 10% chance to capture a worker, and in testing it worked out to approximately this ratio).

I am confused. You said when you do not test the random number, it always generates the worker. And when you do test the random number, it generates the worker about 10% of the time. Isn't this what you are trying to do? What is not working?

Also, I realize that starting my integers with i, pointers with p and booleans with b is merely a convention, but do you think it's one I should continue with?

Yes.
 
I am confused. You said when you do not test the random number, it always generates the worker. And when you do test the random number, it generates the worker about 10% of the time. Isn't this what you are trying to do? What is not working?

When I use the condition "iNumber < 1" it generates the worker 10% of the time. When I use the condition "iNumber < iTestNumber" after setting iTestNumber to either 1 or 2, it does not generate the worker.
 
I cannot think of any reason for that. Is there an indentation (white space) problem? Are any python messages printed to PythonErr.log? You may want to try adding a print statement to see what values come up.
 
I cannot think of any reason for that. Is there an indentation (white space) problem? Are any python messages printed to PythonErr.log? You may want to try adding a print statement to see what values come up.

I have actually made a change that works. It is now this:

Code:
if pWinner.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SLAVEMAKER')) and iNumber < iTestNumber and not bAnimal:

And that seems to have done it.
 
You can simplify your bAnimal check by using the isAnimal() call on the loosing unit, rather then looking up individual strings:
Code:
if (unitLoser.isAnimal()):
	bAnimal = True
 
You can simplify your bAnimal check by using the isAnimal() call on the loosing unit, rather then looking up individual strings:
Code:
if (unitLoser.isAnimal()):
	bAnimal = True

Thanks! I didn't know such a function existed. While we're on the subject, is there any database of functions, so I can simplify such things in the future?
 
Top Bottom