# 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 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 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 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
sta result
lda result+1
sta result+1
dex
bpl mul6

; now accumulator= random from 0-5 inclusive```

Ahh, thank you!

##### Share on other sites

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

```

##### 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 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 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
lsr
lsr
lsr
lsr
lsr
STA temp1
```

##### 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
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 on other sites
Posted (edited)

another possibility

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

```

produces

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

```

Edited by bogax

##### Share on other sites
Posted (edited)
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
ror
lsr
lsr
lsr
lsr
lsr
sta temp1
end

```

Edited by bogax

##### 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?

##### Share on other sites
Posted (edited)
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

##### 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

##### 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.

## Join the conversation

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

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

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