File: random_gen.c

package info (click to toggle)
rockdodger 0.9.2-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 2,220 kB
  • ctags: 756
  • sloc: ansic: 5,374; makefile: 159; sh: 21
file content (62 lines) | stat: -rw-r--r-- 1,797 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "random_gen.h"
#include <time.h>
#include <stdlib.h>
#ifdef DEBUG
#include <stdio.h>
#endif

#define RANDOM_LIST_SIZE (1L<<18)
static float random_list[RANDOM_LIST_SIZE];
static unsigned long random_list_index;
static unsigned long new_random_index = 0;

/*
 * Random numbers involve a call to the operating system, and may take some
 * time to complete. I can't call the random number generator multiple times
 * per frame.  In one old version, it would take half a second before the ship
 * explosion was generated when the rnd() function was calling the operating
 * system function.
 * The solution is to generate random numbers during initialisation, and store
 * in a circular array.  This will (of course) repeat, but it is not noticeable
 * (unless RANDOM_LIST_SIZE is very very small).
 */

float rnd_next_float() {
  return (float) random() / (float) RAND_MAX;
}

void initrnd() {
  unsigned long i;
  time_t starttime;

  if(time(&starttime) != -1) {
    srandom((unsigned int) starttime);
  }
  for(i = 0; i < RANDOM_LIST_SIZE; i++) {
    random_list[i] = rnd_next_float();
  }
  random_list_index = 0;
#ifdef DEBUG
  float min = *random_list;
  float max = *random_list;
  for(i = 0; i < RANDOM_LIST_SIZE; ++i) {
    float next = random_list[i];
    if(next < min) min = next;
    if(next > max) max = next;
  }
  printf("%ld random numbers have been initialised (min=%g, max=%g).\n", RANDOM_LIST_SIZE, min, max);
#endif
}


float rnd() {
  if(++random_list_index >= RANDOM_LIST_SIZE) {
    random_list_index = 0;
    //From time to time insert a new random number to keep the list "fresh".
    random_list[new_random_index++ % RANDOM_LIST_SIZE] = rnd_next_float();
#ifdef DEBUG
    puts("Random numbers are recycled!");
#endif
  }
  return random_list[random_list_index];
}