2

I am making a game on a PIC18F2550 and I need to create a random number between 1 and 4. I've found out already that the rand() function sucks for truly random numbers. I've tried the srand(time(NULL)), this is the main file

#include <time.h>
#include <stdlib.h>
#include <stdio.h>
void main(void) {
    srand(time(NULL));
    init(); 
    while(timed_to_1ms()) {
        fsm_game();
    }
}

this is the fsm_game.c file

void randomSpawn(int time2) {
    if(counter%time2==0) { 
        int x = rand()%4 +1; // Makes number between 1 and 4
    }
}

When I try to build this I get an error saying:

":0: error: (499) undefined symbol: _time(dist/default/production\Dontcrash.production.obj) "

I think the problem may be in the fact that a microProcessor doesn't 'know the time', so if that's the case, what can I do to solve this problem?

niklas3524
  • 21
  • 1
  • 2
  • 2
    Computer(microcontroller) programs are *deterministic*. An external source of entropy is needed to generate "truly" random numbers. In your case it is the time, which is not really random. So the answer is - you can't, unless you have some hardware to provide you with entropy. But apparently this is not your question at all. You can use some analog input with some temperature-sensitive circuitry connected instead of the time. – Eugene Sh. May 11 '18 at 19:22
  • Related: https://stackoverflow.com/q/22284025/1679849 – r3mainer May 11 '18 at 19:59

3 Answers3

1

To initialize the random number generator you could read the voltage present on a floating pin with the PIC's ADC, and set the seed with srand().

Additionally, you could save the seed to EEPROM every time the program starts, and read the previous seed value from EEPROM, combine it with the ADC value to make things less predictable. - I think this would be good enough for a game, otherwise that would be too crude I guess.

unsigned int seed = read_seed_from_adc();
seed ^= read_seed_from_eeprom(); /* use something else than XOR here */
srand(seed);
write_seed_to_eeprom(seed);

I think the problem may be in the fact that a microProcessor doesn't 'know the time', so if that's the case, what can I do to solve this problem?

Time is usually measured with an RTC on a microcontroller, so it depends on your hardware if the RTC can be used (the RTC usually needs an quartz resonator and a backup battery to keep it running all the time, some micros use an external RTC). Since most often only a small C library is used on microcontrollers, time() usually will not be available, and you would need to read out the RTC registers yourself. - It could also be used to initialize the PRNG.

rel
  • 764
  • 5
  • 18
0

Since your PIC doesn't have a hardware RNG, you'll have to settle for a software PRNG. Yes, the one in many C libraries is not very good (though many modern compilers are getting better). For small embedded systems, I like to use Marsaglia's XOR shift:

static uint32_t rng_state;
uint32_t rng_next() {
    rng_state ^= (rng_state << 13);
    rng_state ^= (rng_state >> 17);
    rng_state ^= (rng_state << 5);
    return rng_state - 1;
}

You seed the above by just setting rng_state to an initial value (other than 0).

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
  • This won't meet the request to create truly random numbers. In fact, if the algorithm is known it is 100% predictable -- add 1 to the return value and perform the same set of calculations to get the next value. At a minimum you should use a PRNG that collapses a larger state into the return value, so that the state is not 1:1 with the output. – pjs May 12 '18 at 15:53
0

"Anyone who attempts to generate random numbers by deterministic means is, of course, living in a state of sin." - John von Neumann

There are sources of true random numbers on the internet, such as LavaRnd.

It is also possible to get some physical random input from your computer's microphone socket, as long as there is no microphone connected. That will deliver thermal noise which can be used as a basis for a TRNG. Best to gather a large quantity of the data, at least fifty times as many bits or more for security, and extract the entropy with a good quality cryptographic hash function. You will need to experiment, depending on how much entropy your equipment delivers.

More complex would be a full implementation of Fortuna or similar, which gather entropy from a number of sources.

Most expensive would be to purchase a true random source on a card and install that.

rossum
  • 15,344
  • 1
  • 24
  • 38