### Is the Random Function broken for anyone else?

Void777 · 4 · 1183

#### Void777

• Full Member
• Posts: 16
So, im trying to pick a random.choice in micropython. For whatever reason, it always picks the same number based on the number i pick. For example if i pick the first option, it will always pick the third. if i pick the second, it will always pick the first. If i pick the third it will always pick the first. Ive checked my code and executed it at least 30 times with the same results. Has anyone else encouneterd this?

#### rli

• Jr. Member
• Posts: 8
Do you have example code? I think I was able to reproduce the issue you're describing.

I believe the "problem" is that the random number generator's seed doesn't change between runs of the emulator.

Here's my test:
Code: [Select]
`import randomimport timel = [0,1,2,3]for i in range(20):    r = random.choice(l)    print(f"{i}: {r}")# Outputs:# 0: 1# 1: 0# 2: 1# 3: 3# 4: 0# 5: 3# 6: 3# 7: 3# 8: 1# 9: 1# 10: 3# 11: 3# 12: 3# 13: 1# 14: 1# 15: 2# 16: 1# 17: 2# 18: 3# 19: 1`
The output is the same each time.

Relevant documentation: https://docs.micropython.org/en/latest/library/random.html?highlight=random#random.seed

Some usual tricks for initializing a seed for less deterministic results is passing in the time, but because the emulator has no true Real Time Clock(RTC) or this MICROPY_PY_URANDOM_SEED_INIT_FUNC setting enabled, all the random number functions will act deterministically.

In practice, you might be fine with passing the time.ticks_ms() or time.ticks_us() as the seed (https://docs.micropython.org/en/latest/library/time.html?highlight=time#time.ticks_ms):
Code: [Select]
`import randomimport timerandom.seed(time.ticks_us()) # Relies on minor inconsistencies to differ a little each timel = [0,1,2,3]for i in range(20):    r = random.choice(l)    print(f"{i}: {r}")`
It's not great and depending on how early on in the execution you're getting random numbers, it might get the same seed more often than not.

EDIT: I'm just stating what appears to be happening in the emulator. I don't know if the actual hardware will implement the micropython option or at least have working RTC so we can have some source of noise. Maybe the engineers/devs can answer?
« Last Edit: October 17, 2021, 02:48:31 PM by rli »

#### Void777

• Full Member
• Posts: 16
Do you have example code? I think I was able to reproduce the issue you're describing.

I believe the "problem" is that the random number generator's seed doesn't change between runs of the emulator.

Here's my test:
Code: [Select]
`import randomimport timel = [0,1,2,3]for i in range(20):    r = random.choice(l)    print(f"{i}: {r}")# Outputs:# 0: 1# 1: 0# 2: 1# 3: 3# 4: 0# 5: 3# 6: 3# 7: 3# 8: 1# 9: 1# 10: 3# 11: 3# 12: 3# 13: 1# 14: 1# 15: 2# 16: 1# 17: 2# 18: 3# 19: 1`
The output is the same each time.

Relevant documentation: https://docs.micropython.org/en/latest/library/random.html?highlight=random#random.seed

Some usual tricks for initializing a seed for less deterministic results is passing in the time, but because the emulator has no true Real Time Clock(RTC) or this MICROPY_PY_URANDOM_SEED_INIT_FUNC setting enabled, all the random number functions will act deterministically.

In practice, you might be fine with passing the time.ticks_ms() or time.ticks_us() as the seed (https://docs.micropython.org/en/latest/library/time.html?highlight=time#time.ticks_ms):
Code: [Select]
`import randomimport timerandom.seed(time.ticks_us()) # Relies on minor inconsistencies to differ a little each timel = [0,1,2,3]for i in range(20):    r = random.choice(l)    print(f"{i}: {r}")`
It's not great and depending on how early on in the execution you're getting random numbers, it might get the same seed more often than not.
I think your probably right, ill try and edit it based on your suggestions, Heres the code for the character select screen, which should select a random opponent based on the character id.
Code: [Select]
`chars = [['goggles', goggles_icon, goggles_icon_selected], ['zap', zap_icon, zap_icon_selected], ['apex', apex_icon, apex_icon_selected]]        for i in range(len(chars)):            thumby.display.blit(box, (16*i) + 5, 0, 16, 16, 1)            if i != selected:                thumby.display.blit(chars[i][1], (16*i) + 5, 0, 16, 16, 1)            else:                thumby.display.blit(chars[i][2], (16*i) + 5, 0, 16, 16, 1)        if thumby.buttonR.pressed() and selected < len(chars):            selected += 1        elif thumby.buttonL.pressed() and selected > 0:            selected -= 1        elif thumby.buttonA.pressed():            selected_char = chars[selected][0]            enemy_char_data = random.choice(chars)            enemy_char = enemy_char_data[0]            while enemy_char == selected_char:                enemy_char_data = random.choice(chars)                enemy_char = enemy_char_data[0]            thumby.display.fill(1)            select_screen = False            singleplayer_battle(selected_char, enemy_char)        time.sleep(0.1)        thumby.display.update()        i = 0`

#### Jason

• Full Member
• Posts: 47
• TinyCircuits Employee
The random number returning the same number should happen both on hardware and in the emulator.

In the case of your game, a more reliable way to seed the random number generator is to feed
Code: [Select]
`random.seed(seed)` the passed time/ticks using
Code: [Select]
`time.ticks_us()` or
Code: [Select]
`time.ticks_ms()` after the user selects a character. It is unlikely that a user will select a character at the same milli or micro second each time (unless maybe they hold down the button from game start each time).

SMF spam blocked by CleanTalk