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