Apply the new ground_level method.
[crawl.git] / crawl-ref / source / random-var.cc
blob794e3c152bb0c824c1e5e5d58ea6eea43f7246bc
1 #include "AppHdr.h"
3 #include "random-var.h"
5 #include "random.h"
7 random_var::random_var(int c)
8 : start(c), end(c+1)
10 weights.push_back(1);
11 init();
14 random_var::random_var(int s, int e, weight_func w)
15 : start(s), end(e)
17 init_weights(w);
18 init();
21 random_var::random_var(int s, int e, std::vector<int> ws)
22 : start(s), end(e), weights(ws)
24 ASSERT(weights.size() == static_cast<unsigned int>(end - start));
25 init();
28 const random_var& random_var::operator=(const random_var& other)
30 start = other.start;
31 end = other.end;
32 total = other.total;
33 weights = other.weights;
34 return (*this);
37 int random_var::weight(int val) const
39 if (val < start || val >= end)
40 return (0);
41 return (weights[val - start]);
44 void random_var::init_weights(weight_func w)
46 ASSERT(weights.empty());
47 for (int v = start; v < end; ++v)
48 weights.push_back(w ? (*w)(v) : 1);
51 void random_var::init()
53 total = 0;
54 for (int v = start; v < end; ++v)
55 total += weight(v);
56 ASSERT(total > 0);
57 ASSERT(weight(start) > 0 && weight(end - 1) > 0);
60 int random_var::roll2val(int r) const
62 ASSERT(0 <= r && r < total);
63 int v = start;
64 int w = weight(v);
65 while (r >= w)
67 v++;
68 w += weight(v);
70 return (v);
73 int random_var::roll() const
75 return (roll2val(random2(total)));
78 int random_var::max() const
80 return (end - 1);
83 int random_var::min() const
85 return (start);
88 double random_var::expected() const
90 double ev = 0;
91 for (int i = start; i < end; ++i)
92 ev += i * weight(i) / (double)total;
93 return (ev);
97 //////////////////////////////////
99 random_var constant(int n)
101 return (random_var(n));
104 random_var operator+(const random_var& x, const random_var& y)
106 const int start = x.min() + y.min();
107 const int end = x.max() + y.max() + 1;
108 std::vector<int> weights(end - start, 0);
110 for (int vx = x.min(); vx <= x.max(); ++vx)
111 for (int vy = y.min(); vy <= y.max(); ++vy)
112 weights[vx + vy - start] += x.weight(vx) * y.weight(vy);
114 return (random_var(start, end, weights));
117 random_var negate(const random_var& x)
119 const int start = -x.max();
120 const int end = -x.min() + 1;
121 std::vector<int> weights(end - start, 0);
123 for (int v = x.min(); v <= x.max(); ++v)
124 weights[-v - start] = x.weight(v);
126 return (random_var(start, end, weights));
129 random_var operator-(const random_var& x, const random_var& y)
131 return (x + negate(y));
134 const random_var& operator+=(random_var& x, const random_var& y)
136 x = x + y;
137 return (x);
140 const random_var& operator-=(random_var& x, const random_var& y)
142 x = x - y;
143 return (x);
146 random_var operator/(const random_var& x, int d)
148 const int start = x.min() / d;
149 const int end = x.max() / d + 1;
150 std::vector<int> weights(end - start, 0);
152 for (int v = x.min(); v <= x.max(); ++v)
153 weights[v/2 - start] += x.weight(v);
155 return (random_var(start, end, weights));
158 random_var rv::max(const random_var& x, const random_var& y)
160 const int start = std::max(x.min(), y.min());
161 const int end = std::max(x.max(), y.max()) + 1;
162 std::vector<int> weights(end - start, 0);
164 for (int vx = x.min(); vx <= x.max(); ++vx)
165 for (int vy = y.min(); vy <= y.max(); ++vy)
166 weights[std::max(vx, vy) - start] += x.weight(vx) * y.weight(vy);
168 return (random_var(start, end, weights));
171 random_var rv::min(const random_var& x, const random_var& y)
173 const int start = std::min(x.min(), y.min());
174 const int end = std::min(x.max(), y.max()) + 1;
175 std::vector<int> weights(end - start, 0);
177 for (int vx = x.min(); vx <= x.max(); ++vx)
178 for (int vy = y.min(); vy <= y.max(); ++vy)
179 weights[std::min(vx, vy) - start] += x.weight(vx) * y.weight(vy);
181 return (random_var(start, end, weights));
184 random_var rv::roll_dice(int d, int n)
186 if (n <= 0)
187 return (constant(0));
188 random_var x = constant(0);
189 for (int i = 0; i < d; ++i)
190 x += random_var(1, n+1);
191 return (x);
194 random_var rv::random2(int n)
196 return (random_var(0, std::max(n, 1)));