Generate and use pseudo random numbers
Basic idea
It is very difficult for a computer to generate truly random numbers. However, functions exist which are computationally efficient and generate numbers which seem reasonably random statistically-speaking. These functions are called pseudo random number generators, and the numbers they generate are called pseudo-random numbers. The methodology of how these functions generate these numbers is a computer science topic, beyond the scope of this class. However, given an already-existing pseudo random number generator, it is not difficult to use the function effectively. You just need to understand a few basic principles:
- The pseudo random number generator is truly a function. It accepts one number as input and generates one number as output.
- The input number is called the random seed.
- The output number the function generates is the pseudo random number and is automatically used by the function as the input for the next time the function is called.
- If we do not initially set the random seed, it may continually default to 0, meaning the function will always generate the same set of random numbers every time. In a game environment this would be deadly, because it would mean we basically have the game behaving exactly the same way every time we play.
- To avoid this, we must start with a reasonably random random seed. Once we have this, the function will happy generate pseudo-random numbers.
- One way to create a random seed is to use a very fast counter to time how long it takes for a user to hit a key. The resulting counter value will be random enough to serve as a reasonable seed.
Application
Application is demonstrated in hello-random.asm
Basic Generation of Random numbers
add to your main code, after a SECTION declaration (perhaps right in front of or behind memory.asm):
INCLUDE "gbrandom.asm"
- In your main code, perhaps right before your main loop, create a screen which tells the user in some sense "press any key to continue."
- This could be your title screen for your game.
- Print this screen to the display, as you have now done many time, perhaps using mem_CopyVRAM
immediately following your call to mem_CopyVRAM, add to your code:
call MakeRandomSeedByTimingKeypress
- this will set a random seed by running a tight loop, counting how long it takes for the user to press any key.
when you want a random number, add to your code:
call Rand16 ; put rand # in hl
- as the comment explains, this will put a random word in hl.
Using random numbers
- when you call Rand16, hl is loaded with a random word i.e. a number between 0 and 65535.
- if you need a number between 0 and 255, just use h or just use l.
You can use bitmasking to easily change the range of your random number to any power of 2 minus 1 (1,3,7,15,31,etc.). For example, if you need a number between 0 and 15, do a bitmask of #00001111 on either h or l and use the result:
call Rand16 ld a,l ; use h if you have something against the letter l and %00001111 ; now a contains a random number between 0 and %00001111=15. ; and %00000011 ; If we did this instead of the above line, a would contain a random number between 0 and 3.
- if you want something to happen with a certain probably, one way is to use the carry flag. Examples:
50% probability:
call Rand16 ld a,l cp 128 ; a - 128 jr c,whatever ; our random number between 0 and 255 is less than 128
25% probability:
call Rand16 ld a,h ; it doesn't matter whether we use h or l cp 64 ; a - 64 jr c,whatever ; our random number between 0 and 255 is less than 64
25% probability:
call Rand16 ld a,l cp 64+128 ; a - 192 jr nc,whatever ; our random number between 0 and 255 is greater than or equal to 192
4ish% probability:
call Rand16 ld a,l cp 1 ; a - 1 jr c,whatever ; our random number between 0 and 255 is less than 1 (i.e. == 0
- For those of you who love the z flag and don't care for the carry flag, you can use bitmasking to set your probability
50% probability:
call Rand16 ld a,l ; use h if you have something against the letter l and %00000001 ; a now contains a random number between 0 and 1. jr nz,whatever; it's not 0, so it must be 1. We got a 50/50 chance.
75% probability:
call Rand16 ld a,l ; use h if you have something against the letter l and %00000011 ; a now contains a random number between 0 and 3. jr nz,whatever; it's not 0, so it must be 1,2, or 3. We got a 75% chance.