]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/lib/random.qc
Small optimization
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / random.qc
1 #include "random.qh"
2
3 ERASEABLE
4 void RandomSelection_Init()
5 {
6         RandomSelection_totalweight = 0;
7         RandomSelection_chosen_ent = NULL;
8         RandomSelection_chosen_float = 0;
9         RandomSelection_chosen_string = string_null;
10         RandomSelection_best_priority = -1;
11 }
12
13 ERASEABLE
14 void RandomSelection_Add(entity e, float f, string s, vector v, float weight, float priority)
15 {
16         if (priority > RandomSelection_best_priority)
17         {
18                 RandomSelection_best_priority = priority;
19                 RandomSelection_chosen_ent = e;
20                 RandomSelection_chosen_float = f;
21                 RandomSelection_chosen_string = s;
22                 RandomSelection_chosen_vec = v;
23                 RandomSelection_totalweight = weight;
24         }
25         else if (priority == RandomSelection_best_priority)
26         {
27                 RandomSelection_totalweight += weight;
28                 if (random() * RandomSelection_totalweight <= weight)
29                 {
30                         RandomSelection_chosen_ent = e;
31                         RandomSelection_chosen_float = f;
32                         RandomSelection_chosen_string = s;
33                         RandomSelection_chosen_vec = v;
34                 }
35         }
36 }
37
38 float DistributeEvenly_amount;
39 float DistributeEvenly_totalweight;
40
41 ERASEABLE
42 void DistributeEvenly_Init(float amount, float totalweight)
43 {
44         if (DistributeEvenly_amount)
45         {
46                 LOG_TRACE("DistributeEvenly_Init: UNFINISHED DISTRIBUTION (", ftos(DistributeEvenly_amount), " for ", ftos(DistributeEvenly_totalweight), " left!)");
47         }
48         if (totalweight == 0) DistributeEvenly_amount = 0;
49         else DistributeEvenly_amount = amount;
50         DistributeEvenly_totalweight = totalweight;
51 }
52
53 ERASEABLE
54 float DistributeEvenly_Get(float weight)
55 {
56         float f;
57         if (weight <= 0) return 0;
58         f = floor(0.5 + DistributeEvenly_amount * weight / DistributeEvenly_totalweight);
59         DistributeEvenly_totalweight -= weight;
60         DistributeEvenly_amount -= f;
61         return f;
62 }
63
64 ERASEABLE
65 float DistributeEvenly_GetRandomized(float weight)
66 {
67         float f;
68         if (weight <= 0) return 0;
69         f = floor(random() + DistributeEvenly_amount * weight / DistributeEvenly_totalweight);
70         DistributeEvenly_totalweight -= weight;
71         DistributeEvenly_amount -= f;
72         return f;
73 }
74
75 // from the GNU Scientific Library
76 float gsl_ran_gaussian_lastvalue;
77 float gsl_ran_gaussian_lastvalue_set;
78 ERASEABLE
79 float gsl_ran_gaussian(float sigma)
80 {
81         if (gsl_ran_gaussian_lastvalue_set)
82         {
83                 gsl_ran_gaussian_lastvalue_set = 0;
84                 return sigma * gsl_ran_gaussian_lastvalue;
85         }
86         else
87         {
88                 float a = random() * 2 * M_PI;
89                 float b = sqrt(-2 * log(random()));
90                 gsl_ran_gaussian_lastvalue = cos(a) * b;
91                 gsl_ran_gaussian_lastvalue_set = 1;
92                 return sigma * sin(a) * b;
93         }
94 }
95
96 // prandom - PREDICTABLE random number generator (not seeded yet)
97
98 #ifdef USE_PRANDOM
99         float prandom_seed;
100         float prandom()
101         {
102                 float c;
103                 c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
104                 prandom_seed = c;
105
106         #ifdef USE_PRANDOM_DEBUG
107                         LOG_TRACE("RANDOM -> ", ftos(c));
108         #endif
109
110                 return c / 65536;  // in [0..1[
111         }
112
113         vector prandomvec()
114         {
115                 vector v;
116
117                 do
118                 {
119                         v.x = prandom();
120                         v.y = prandom();
121                         v.z = prandom();
122                 }
123                 while (v * v > 1);
124
125                 return v;
126         }
127
128         void psrandom(float seed)
129         {
130                 prandom_seed = seed;
131         #ifdef USE_PRANDOM_DEBUG
132                         LOG_TRACE("SRANDOM ", ftos(seed));
133         #endif
134         }
135
136         #ifdef USE_PRANDOM_DEBUG
137                 void prandom_debug()
138                 {
139                         LOG_TRACE("Current random seed = ", ftos(prandom_seed));
140                 }
141         #endif
142 #endif