Cuberite
A lightweight, fast and extensible game server for Minecraft
ProbabDistrib.cpp
Go to the documentation of this file.
1 
2 // ProbabDistrib.cpp
3 
4 // Implements the cProbabDistrib class representing a discrete probability distribution curve and random generator
5 
6 #include "Globals.h"
7 #include "ProbabDistrib.h"
8 
9 
10 
11 
12 
14  m_MaxValue(a_MaxValue),
15  m_Sum(-1)
16 {
17 }
18 
19 
20 
21 
22 
24 {
25  ASSERT(!a_Points.empty());
26  m_Sum = 0;
27  m_Cumulative.clear();
28  m_Cumulative.reserve(a_Points.size() + 1);
29  int ProbSum = 0;
30  int LastProb = 0;
31  int LastValue = -1;
32  if (a_Points[0].m_Value != 0)
33  {
34  m_Cumulative.emplace_back(0, 0); // Always push in the [0, 0] point for easier search algorithm bounds
35  LastValue = 0;
36  }
37  for (cPoints::const_iterator itr = a_Points.begin(), end = a_Points.end(); itr != end; ++itr)
38  {
39  if (itr->m_Value == LastValue)
40  {
41  continue;
42  }
43 
44  // Add the current trapezoid to the sum:
45  ProbSum += (LastProb + itr->m_Probability) * (itr->m_Value - LastValue) / 2;
46  LastProb = itr->m_Probability;
47  LastValue = itr->m_Value;
48  m_Cumulative.emplace_back(itr->m_Value, ProbSum);
49  } // for itr - a_Points[]
50  if (LastValue != m_MaxValue)
51  {
52  m_Cumulative.emplace_back(m_MaxValue, 0); // Always push in the last point for easier search algorithm bounds
53  }
54  m_Sum = ProbSum;
55 }
56 
57 
58 
59 
60 
61 bool cProbabDistrib::SetDefString(const AString & a_DefString)
62 {
63  AStringVector Points = StringSplitAndTrim(a_DefString, ";");
64  if (Points.empty())
65  {
66  return false;
67  }
68  cPoints Pts;
69  for (AStringVector::const_iterator itr = Points.begin(), end = Points.end(); itr != end; ++itr)
70  {
71  AStringVector Split = StringSplitAndTrim(*itr, ",");
72  if (Split.size() != 2)
73  {
74  // Bad format
75  return false;
76  }
77  int Value = atoi(Split[0].c_str());
78  int Prob = atoi(Split[1].c_str());
79  if (
80  ((Value == 0) && (Split[0] != "0")) ||
81  ((Prob == 0) && (Split[1] != "0"))
82  )
83  {
84  // Number parse error
85  return false;
86  }
87  Pts.emplace_back(Value, Prob);
88  } // for itr - Points[]
89 
90  SetPoints(Pts);
91  return true;
92 }
93 
94 
95 
96 
97 
98 int cProbabDistrib::Random(MTRand & a_Rand) const
99 {
100  return MapValue(a_Rand.RandInt(m_Sum));
101 }
102 
103 
104 
105 
106 
107 int cProbabDistrib::MapValue(int a_OrigValue) const
108 {
109  ASSERT(a_OrigValue >= 0);
110  ASSERT(a_OrigValue < m_Sum);
111 
112  // Binary search through m_Cumulative for placement:
113  size_t Lo = 0;
114  size_t Hi = m_Cumulative.size() - 1;
115  while (Hi - Lo > 1)
116  {
117  size_t Mid = (Lo + Hi) / 2;
118  int MidProbab = m_Cumulative[Mid].m_Probability;
119  if (MidProbab < a_OrigValue)
120  {
121  Lo = Mid;
122  }
123  else
124  {
125  Hi = Mid;
126  }
127  }
128  ASSERT(Hi - Lo == 1);
129 
130  // Linearly interpolate between Lo and Hi:
131  int ProbDif = m_Cumulative[Hi].m_Probability - m_Cumulative[Lo].m_Probability;
132  ProbDif = (ProbDif != 0) ? ProbDif : 1;
133  int ValueDif = m_Cumulative[Hi].m_Value - m_Cumulative[Lo].m_Value;
134  return m_Cumulative[Lo].m_Value + (a_OrigValue - m_Cumulative[Lo].m_Probability) * ValueDif / ProbDif;
135 }
136 
137 
138 
139 
#define ASSERT(x)
Definition: Globals.h:276
AStringVector StringSplitAndTrim(const AString &str, const AString &delim)
Split the string at any of the listed delimiters and trim each value.
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
Class to wrap any random engine to provide a more convenient interface.
Definition: FastRandom.h:58
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
void SetPoints(const cPoints &a_Points)
Sets the distribution curve using an array of [value, probability] points, linearly interpolated.
cPoints m_Cumulative
Cumulative probability of the values, sorted, for fast bsearch lookup.
Definition: ProbabDistrib.h:69
cProbabDistrib(int a_MaxValue)
bool SetDefString(const AString &a_DefString)
Sets the distribution curve using a definition string; returns true on successful parse.
int Random(MTRand &a_Rand) const
Gets a random value from a_Rand, shapes it into the distribution curve and returns the value.
std::vector< cPoint > cPoints
Definition: ProbabDistrib.h:45
int m_Sum
Sum of all the probabilities across all values in the domain; -1 if not set.
Definition: ProbabDistrib.h:72
int MapValue(int a_OrigValue) const
Maps value in range [0, m_Sum] into the range [0, m_MaxValue] using the stored probability.