Heaven/TQA Posted July 16, 2007 Share Posted July 16, 2007 (edited) what is your fave routine to get random values between x and y? right now i am using this: ;input x,y (range) ;output a = random[x,y] get_random: rand00 stx rand0+1;20 sty rand1+1;10 ;check x<y if so then switch order cpy rand0+1 beq rand01 bcs rand stx rand1+1 sty rand0+1 rand lda 53770;atari800 random register (0-255) rand0 cmp #0;20 bcc rand rand1 cmp #0;10 bcs rand rts rand01 txa ;x=y=a rts but is there a quicker solution? Edited July 16, 2007 by Heaven/TQA Quote Link to comment Share on other sites More sharing options...
DEBRO Posted July 16, 2007 Share Posted July 16, 2007 Hi there, What I do is get the number between 0 and max - min and add min to the value. For instance, when I needed a number between 9 and 136 I'd call the random routine which would generate a byte so the value would be 0 <= a <= 255. Then I'd divide the value by 2 so it's now 0 <= a <= 127. Next I'd add 9 so now the value is 9 <= a <= 136. I hope that makes sense. Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted July 16, 2007 Author Share Posted July 16, 2007 but what if you dont know the range as the range could be as well completly random? Quote Link to comment Share on other sites More sharing options...
DEBRO Posted July 16, 2007 Share Posted July 16, 2007 but what if you dont know the range as the range could be as well completly random?Maybe I'm suffering from tunnel vision. When would you not know the range you're trying to achieve? I guess I could see that if you were trying to make a generic routine. Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted July 17, 2007 Author Share Posted July 17, 2007 Debro... i am coding an action RPG at the moment and in the game a lot of things are based on randomness, sometimes in a controlled way. f.e the damage of a weapon is based on the weapon stats and the player stats... simplified think about a dagger with attack range of 2-4 hitpoints... other weapons might have a range from 10-20 etc... and even the attack itself is based on rolling a dice (0-99) and testing against some values... the issue here is that i do not know what kind of ranges are needed...thats why i would like to have a fast but generic random routine. the only random routine which could be optimised (and i guess i will do that...) is the RAND(100) function... i hope its little bit clearer now. Quote Link to comment Share on other sites More sharing options...
Robert M Posted July 19, 2007 Share Posted July 19, 2007 I don't know if I can offer a faster routine in all cases, but the one below does have a guaranteed worst case execution time. Cheers! Rob SUBROUTINE Answer DS.W 1; Allocate 16-bits Adder DS.W 1; Allocate 16-bits Mult DS.B 1; lobyte EQU 0; byte offsets into Answer and Adder. hibyte EQU 1 RangedRandom ; Given X = min, and Y = max; where 0 <= X <= Y <= 254 ; Returns a random number in A, between min and max inclusive ; in linear time. STX Answer.hibyte; Start at the minimum posible value. TYA; A = max SEC ; Calculate the number of possible values SBC min ; that could be returned as max - min + 1 ADC #0 ; Carry is always set by previous subtraction. STA Adder.lobyte; Fraction to be mulitplied 0 - 255 times. ; and added to min to form the answer. LDA #0 STA Adder+hibyte; Adder = 00:max-min+1 STA Answer+lobyte; Answer = min:00 LDA 53770;atari800 random register (0-255) whileMultNotZeroDo ; This loop executes 0 to 8 times. BEQ .Done LSR ; check if next bit in Mult is set. STA Mult BCC .skipAdd CLC ; Add Adder to Answer (16-bit addition). LDA Answer+lobyte ADC Adder+lobyte STA Answer+lobyte LDA Answer+hibyte ADC Adder+hibyte STA Answer+hibyte .skipAdd ASL Adder+lobyte; Multiply the 16-bit adder by 2 every ROL Adder+hibyte; time through the loop. x1,x2,x4,...,x128 LDA Mult BCC whileMultNotZeroDo; branch is always taken. .Done LDA Answer+hibyte; A = random # in range min to max. RTS ; X = min; Y = max Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted July 19, 2007 Author Share Posted July 19, 2007 (edited) Thanks Rob, have to check on weekend. btw. could be a RAND(100) done like that? lda 53770 ; (random value 0-255) lsr lsr clc adc #36 ??? Edited July 19, 2007 by Heaven/TQA Quote Link to comment Share on other sites More sharing options...
Kurt_Woloch Posted July 19, 2007 Share Posted July 19, 2007 btw. could be a RAND(100) done like that? lda 53770 ; (random value 0-255) lsr lsr clc adc #36 ??? I don't think this would work... you convert the random value 0-255 to 0-63, and then add #36 to that... which gives a random value in the range of 36 to 99... not 0 to 99 as you probably would like it to be (unless the LSR command does something else than I expect). Quote Link to comment Share on other sites More sharing options...
Robert M Posted July 20, 2007 Share Posted July 20, 2007 Thanks Rob, have to check on weekend. btw. could be a RAND(100) done like that? lda 53770 ; (random value 0-255) lsr lsr clc adc #36 ??? When you say a RAND(100) function, I am guessing that you mean you want the random value returned to be in BCD format. If that is what you mean, then it is possible. We just need to feed the routine min and max numbers in BCD format, and use BCD math internally. My untested BCD version of the routine is below. The routine is slowed a bit by using BCD, but not much. Cheers! SUBROUTINE Answer DS.W 1; Allocate 16-bits Adder DS.W 1; Allocate 16-bits Mult DS.B 1; lobyte EQU 0; byte offsets into Answer and Adder. hibyte EQU 1 BCDRangedRandom ; NOTE: This routine assumes inputs in BCD format, and returns ; a BCD value in A. ; Given X = min, and Y = max; where 0 <= X <= Y <= 99 [BCD] ; Returns a random number in A, between min and max inclusive ; in BCD format. SED ; Put the processor in BCD math mode. STX Answer.hibyte; Start at the minimum posible value. TYA ; A = max SEC ; Calculate the number of possible values SBC min ; that could be returned as max - min + 1 ADC #0 ; Carry is always set by previous subtraction. STA Adder.lobyte; Fraction to be mulitplied 0 - 255 times. ; and added to min to form the answer. LDA #0 STA Adder+hibyte; Adder = 00:max-min+1 STA Answer+lobyte; Answer = min:00 LDA 53770;atari800 random register (0-255) whileMultNotZeroDo ; This loop executes 0 to 8 times. BEQ .Done LSR ; check if next bit in Mult is set. STA Mult BCC .skipAdd CLC ; Add Adder to Answer (16-bit addition). LDA Answer+lobyte ADC Adder+lobyte STA Answer+lobyte LDA Answer+hibyte ADC Adder+hibyte STA Answer+hibyte .skipAdd ; a BCD number can not be shifted to mulitply by 2. ; instead the code must add the BCD number it to itself. ; Carry should always be 0 at this point so no CLC is needed here. LDA Adder+lobyte ADC Adder+lobyte STA Adder+lobyte LDA Adder+hibyte ADC Adder+hibyte; Multiply the 16-bit adder by 2 every STA Adder+hibyte; time through the loop. x1,x2,x4,...,x128 LDA Mult BCC whileMultNotZeroDo; branch is always taken. .Done CLD ; Turn off BCD math mode. LDA Answer+hibyte; A = random # in range min to max. RTS ; X = min; Y = max Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted July 20, 2007 Author Share Posted July 20, 2007 bcd could be interesting... another approach could be using RAND(96) instead of RAND(100) which could be a good compromise rand100: lda 53770;(0-255) and #$1f;0-31 sta rand100b+1 lda 53770;(0-255) and #$3f clc rand100b: adc #0;add rand(0-31) rts ? Quote Link to comment Share on other sites More sharing options...
Robert M Posted July 20, 2007 Share Posted July 20, 2007 bcd could be interesting... another approach could be using RAND(96) instead of RAND(100) which could be a good compromise rand100: lda 53770;(0-255) and #$1f;0-31 sta rand100b+1 lda 53770;(0-255) and #$3f clc rand100b: adc #0;add rand(0-31) rts ? That code would produce a number between 0 and 94. The distribution would be more of a bell curve. It would be less likely to get very high and very low values. Which may be desirable. Quote Link to comment Share on other sites More sharing options...
The Electric Monk Posted August 3, 2007 Share Posted August 3, 2007 Is 'LDA 53770' legal in 6502 for the 2600? All the random number algorithms I've seen before take advantage (I think) of the fact that the 2600 powers up in a random state, so the contents of any memory address can serve as a seed for an LFSR (it's called something like that) algorithm. This seems much easier if it's kosher. Thanks, Jason Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted August 3, 2007 Share Posted August 3, 2007 Is 'LDA 53770' legal in 6502 for the 2600? All the random number algorithms I've seen before take advantage (I think) of the fact that the 2600 powers up in a random state, so the contents of any memory address can serve as a seed for an LFSR (it's called something like that) algorithm. This seems much easier if it's kosher. Thanks, Jason Legal, yes. It's actually address $D20A - which is a mirror for romspace. If used on the 2600, you would be reading an unchanging value (unless something other than native hardware is involved - i.e. Supercharger, etc). So it would not be applicable to this discussion. The address is a random number generator in the Atari computer line. Your second part is valid, so long as the 7800 isn't being used to play the game (this powers up with known values in Ram...making it possible to "autodetect" if that console is being used vs. the 2600 or emulators). Quote Link to comment Share on other sites More sharing options...
The Electric Monk Posted August 15, 2007 Share Posted August 15, 2007 Is 'LDA 53770' legal in 6502 for the 2600? All the random number algorithms I've seen before take advantage (I think) of the fact that the 2600 powers up in a random state, so the contents of any memory address can serve as a seed for an LFSR (it's called something like that) algorithm. This seems much easier if it's kosher. Thanks, Jason Legal, yes. It's actually address $D20A - which is a mirror for romspace. If used on the 2600, you would be reading an unchanging value (unless something other than native hardware is involved - i.e. Supercharger, etc). So it would not be applicable to this discussion. The address is a random number generator in the Atari computer line. Your second part is valid, so long as the 7800 isn't being used to play the game (this powers up with known values in Ram...making it possible to "autodetect" if that console is being used vs. the 2600 or emulators). Belated thanks, Nukey. That makes sense. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.