Mike wrote: ↑Mon Nov 27, 2023 5:00 am
Timer based methods, together with human interaction, are however a good method to obtain a
seed. Any further random number generation can use that seed, but should otherwise be completely deterministic.
One thing I learned the hard way was this: I had a tape-based game seed a random number generator with the timer. When I converted this game to cartridge, the levels became deterministic, because unlike LOAD/RUN from tape, a cartridge always starts up in the same way every time. So I moved back the seed to the first human interaction of starting the game.
Mike wrote: ↑Mon Nov 27, 2023 5:00 amGenerally, timer based methods suffer from correlations with the execution time of the client program
This has been my experience. Tying pseudorandom numbers
too closely to any cycle-based timer is problematic, because routines will tend to be executed at consistent intervals, and take a consistent number of cycles. So you will see patterns that are hard to account for unless you realize that. I suspect that may be an issue with your randomgen_y routine above, MrSterlingBS. I tried something like this to generate mazes once, and I was dismayed at the result.
A shift register provides a sort of extra layer between the timer-based seed and the results. Here's the random number generator that I use (I add and remove the Rand
X entry points as needed). The entry point determines the bit length of the result. RNDNUM is a temporary storage location for the result, and P_RAND is the 16-bit seed (see below):
Code: Select all
; Pseudo Random
Rand3: lda #%01000000 ; 2-bit entry point
.byte $3c ; Skip word (SKW)
Rand31: lda #%00001000 ; 5-bit entry point
.byte $3c ; Skip word (SKW)
Rand255: lda #%00000001 ; 8-bit entry point
PRand: sta RNDNUM
-loop: lsr P_RAND
ror P_RAND+1
bcc shift_rnd
lda P_RAND
eor #$aa
sta P_RAND
lda P_RAND+1
eor #$2b
sta P_RAND+1
shift_rnd: rol RNDNUM
bcc loop
lda RNDNUM
rts
I generate the seed as follows, when the user does something like start the game. The key here is that both seed values are non-zero, hence the ORAs.
Code: Select all
lda TIME_L ; Seed random number generator ($a2)
ora #$01 ; ,,
sta P_RAND ; ,,
lda VIATIME ; ,, ($9114)
ora #$80 ; ,,
sta P_RAND+1 ; ,,
Over the long term, the mean stays very close to 1/2 of the max, and the distribution is good. It's a pithy routine. I probably got it or something like it from this forum somewhere*; as they say, it's good enough for rock and roll**!
________________
* It should come as little surprise that it is based on the routine Mike presented here
https://sleepingelephant.com/ipw-web/bu ... f=2&t=2304
** By "rock and roll" I mean "arcade games."