Jump to content
Captain Spazer

Rnd between 0 and 5?

Recommended Posts

I only have a basic grasp of the rnd, what I learned is thanks too Randomterrains wonderful website. But, I'm in a situation where I need to pick a random number between 0 and 5, is that possible somehow with math wizardry?

Share this post


Link to post
Share on other sites
2 hours ago, Captain Spazer said:

I only have a basic grasp of the rnd, what I learned is thanks too Randomterrains wonderful website. But, I'm in a situation where I need to pick a random number between 0 and 5, is that possible somehow with math wizardry?

How absolutely critical is it that it is in the range 0 to 5?  Can you tweak your logic so that it's 0 to 7?

 

Share this post


Link to post
Share on other sites

Well, the reason is that I got a map grid of 5x5 rooms. If it's not possible, or super hard to do I guess I'll simply have to increase the number of rooms.

I

Share this post


Link to post
Share on other sites

Failing being able to tweak the range, then you could choose a random number (0-255), and multiply by 6 and take the high byte. That will be a random number from 0 to 5.  To multiply by 6 - just add 6 times would be your easiest. Here's an example; it requires a 2-byte zero page variable to hold the working sum. At the end, it spits out a number 0-5 in the accumulator.

 

 ; 6502 implementation

		lda #0
		sta result+1
		sta result

		jsr Rnd				; assumes random 0-255 now in 'rnd'

		ldx #5
mul6		clc
		lda rnd
		adc result
		sta result
		lda result+1
		adc #0
		sta result+1
		dex
		bpl mul6

	; now accumulator= random from 0-5 inclusive

 

Share this post


Link to post
Share on other sites
46 minutes ago, bogax said:

 

temp1 = rand/2 : temp1 = (temp1/2 + temp1)/32

 

 

Very good. Is bB good aware enough to replace the divisions with shifts?

Share this post


Link to post
Share on other sites
8 minutes ago, Andrew Davie said:

Very good. Is bB good aware enough to replace the divisions with shifts?

Yes, assuming of course the division or multiplication is a power of two. 

Share this post


Link to post
Share on other sites
10 minutes ago, Andrew Davie said:

 

Very good. Is bB good aware enough to replace the divisions with shifts?

Yes.

 

this is the asm result

 

 jsr randomize
    lsr
    STA temp1
; complex statement detected
    LDA temp1
    lsr
    CLC
    ADC temp1
    lsr
    lsr
    lsr
    lsr
    lsr
    STA temp1

Share this post


Link to post
Share on other sites
9 minutes ago, bogax said:

Yes.

 

this is the asm result

 

 

 jsr randomize
    lsr
    STA temp1
; complex statement detected
    LDA temp1
    lsr
    CLC
    ADC temp1
    lsr
    lsr
    lsr
    lsr
    lsr
    STA temp1

 

 

Not much wrong with that!  You could drop the CLC and save a couple of cycles and a byte and probably see no difference.

 

Share this post


Link to post
Share on other sites

another possibility

 

 temp1  =  rand  &  63  :  temp1  =  temp1  *  3  /  32

 

produces 

jsr randomize
    AND #63
    STA temp1
; complex statement detected
    LDA temp1
    asl
    clc
    adc temp1
    lsr
    lsr
    lsr
    lsr
    lsr
    STA temp1

Edited by bogax

Share this post


Link to post
Share on other sites
40 minutes ago, Andrew Davie said:

 

Not much wrong with that!  You could drop the CLC and save a couple of cycles and a byte and probably see no difference.

 

also the lda temp1

 

it's not as accurate as [similar] asm could be

 

here's some javascript ranged rand generator

 

the asm it produces

 

asm
jsr randomize
sta temp1
lsr
adc temp1
ror
lsr
lsr
lsr
lsr
lsr
sta temp1
end

 

 

 

 

Edited by bogax

Share this post


Link to post
Share on other sites

I usually just grab stuff from the chart on the bB page until it matches what is needed:

 

a = (rand/64) + (rand/128) + (rand/128)

 

So that would be 0 to 3 plus 0 to 1 plus 0 to 1. Is that a more bloated way to do it?

  • Like 1

Share this post


Link to post
Share on other sites
52 minutes ago, Random Terrain said:

I usually just grab stuff from the chart on the bB page until it matches what is needed:

 

a = (rand/64) + (rand/128) + (rand/128)

 

So that would be 0 to 3 plus 0 to 1 plus 0 to 1. Is that a more bloated way to do it?

 

Don't know bB format, but doing the above using bitmasks instead of shifts would be way quicker...

a = (rand & 3) + (rand & 1) + (rand & 1)

The problem with this approach is that you are calling the random generator each time, and so, it becomes extremely slow in comparison to other methods.

Edited by Andrew Davie
  • Like 1

Share this post


Link to post
Share on other sites
21 minutes ago, Andrew Davie said:

 

Don't know bB format, but doing the above using bitmasks instead of shifts would be way quicker...

a = (rand & 3) + (rand & 1) + (rand & 1)

The problem with this approach is that you are calling the random generator each time, and so, it becomes extremely slow in comparison to other methods.

it's also less random

  • Like 1

Share this post


Link to post
Share on other sites

If you have a grid 5x5 do 0 or 5 have special meaning?

If not and you need a number from 0 to 4 (or 1 to 5 depending on how you index the grid), you could simply have a lookup table somewhere with the numbers 0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,X (that's 16 entries).

You can use the random 0-255 and just take the lowest 4 bits (aka AND 0x0F) as an index in the table.

As you see the last element is X and there are options on how to go about its value/handling:

1) choose one and slightly change the balance (if you choose 0, that value would show up 4/16 instead of 3/16)

2) if you want more randomization you can start with 0 and every time X is the one picked up you add 1 to it so that you spread the unbalance over time (note that in this case the value you read from cell 0x0F has to be AND 0x0F)

3) if X comes up (meaning rand AND 0x0F == 0x0F) you can generate another rand, that happens around 1/16 so the extra cost is not executed that often it is smeared over avg of 15 good picks [actually given the rand gives you 0-255 you can just use the high part when that happens with no extra cost aka (rand AND 0xF0) LSR 4) for in as long as its value is also not 0x0F], note that 1/256 avg you need a 3rd rand, 1/4096 avg you need a 4th etc... etc...

 

The same trick can be done for higher random values that are not perfect powers of two: just find a suitable multiplier that does not generate too big of a table and to which you can find a cheap way to compensate the unbalance. 

 

I do not know if you can spare 16bytes in your game for this table, strictly speaking a single byte can hold 2 values because your numbers are so small (0-4 -> 3bits) ... so it can be reduced to 8bytes (the high part contains one value, the low part the next), you can actually easily compress 3 of those values into one byte by choosing a different ordering for the elements in the lookup table and a suitable encoding if you really have to but that is even more code which may amount to more than the savings.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...