From fb23cf51040f06bfcfbaf318d7b452d76ffbedfb Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Fri, 20 Mar 2026 21:52:36 +0100 Subject: Try to initialize enemies on unique Y coordinates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is, our PRNG algorithm is so stupid that sometimes it cycles into the same value multiple times. While play testing, sometimes we were so unlucky that we got all enemies on the same Y screen coordinate. As funny as these situations can be, this shouldn't happen, so I have introduced an (awesomely named) function that makes a harder effort at finding a unique random number. Signed-off-by: Miquel Sabaté Solà --- src/enemies.s | 2 +- src/jetpac.s | 1 + src/prng.s | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/enemies.s b/src/enemies.s index 6201416..2208758 100644 --- a/src/enemies.s +++ b/src/enemies.s @@ -244,7 +244,7 @@ ;; The Y coordinate is also set at random within the bounds of the ;; playable screen. - jsr Prng::random_valid_y_coordinate + jsr Prng::random_non_repeated_valid_y_coordinate ldx Globals::zp_tmp0 inx sta Enemies::zp_pool_base, x diff --git a/src/jetpac.s b/src/jetpac.s index f99c8b0..3cf8f0a 100644 --- a/src/jetpac.s +++ b/src/jetpac.s @@ -130,6 +130,7 @@ sta Joypad::zp_prev sta Player::zp_state sta Items::zp_state + sta Prng::zp_last_rand ;; Initialize the level. We allow the build system to pass its own value for ;; this in `LEVEL`, just in case we want to debug the enemy of a specific diff --git a/src/prng.s b/src/prng.s index c5ec474..7aa313a 100644 --- a/src/prng.s +++ b/src/prng.s @@ -9,6 +9,14 @@ ;; Current random value. Initialized on the title to game transition. zp_rand = $0A + ;; Last random value as stored by + ;; Prng::random_non_repeated_valid_y_coordinate(). + zp_last_rand = $12 + + ;; How many attempts should Prng::random_non_repeated_valid_y_coordinate() + ;; take to find a unique value. + RAND_ATTEMPTS = 3 + ;; Updates the 'a' register with the next random number set after the ;; current value of `zp_rand`, while also making sure that it is a valid ;; screen Y coordinate. @@ -21,6 +29,33 @@ sta zp_rand rts .endproc + + ;; Calls Prng::random_valid_y_coordinate() multiple times until we get a + ;; different value than what we got the last time we called this + ;; function. Realistically this should just take 1 attempt for most cases, + ;; and in the worst case just 2. Nevertheless, we have set a generous value + ;; to 'RAND_ATTEMPTS' just in case. + ;; + ;; NOTE: the 'y' register is preserved. + .proc random_non_repeated_valid_y_coordinate + tya + pha + ldy #RAND_ATTEMPTS + + @again: + jsr Prng::random_valid_y_coordinate + cmp Prng::zp_last_rand + bne @end + dey + bne @again + + @end: + sta Prng::zp_last_rand + pla + tay + lda Prng::zp_last_rand + rts + .endproc .endscope -- cgit v1.2.3