 FilteredRangeRNG.h

```#ifndef FILTERED_RANGE_RNG_H
#define FILTERED_RANGE_RNG_H

// Sometimes a randomized sequence does not "feel" random to a human. While this isn't
// an indication of an error, sometimes we want to generate values that intuitively
// "feel" random, even if they are actually less-random as a result of this filtering.
// This concept is adapted from Chapter 3 of Steve Rabin, Jay Goldblatt, and Fernando
// Silva's book: "Game AI Pro"

double filteredRangeRNG(double low, double high);

#endif

```

FilteredRangeRNG.cpp

```
// Helper function: Return a random double in range [low, high)
double randRange(double low, double high) { return 1.0 * rand() / RAND_MAX * (high - low) + low; }

// We need to keep track of the most recent rolls
double r = { 0.0, 0.0, 0.0, 0.0, 0.0};
int rc = 0;

// Return a value in range [low, high)
double filteredRangeRNG(double low, double high) {

// Begin by rolling a candidate
double candidate = randRange(low, high);

// If it's the first roll, accept it
if (rc == 0) {
r[rc++] = candidate;
return candidate;
}

// Update the array of the most recent rolls
for (int i = 0; i < rc; i++) { r[i] = r[i + 1]; }
if (rc > 4) { rc = 4; }

// Re-roll if any of the following rules are broken:
// Rule 1: Re-roll if last two consecutive numbers differ by less than 2 percent.
// Rule 2: Re-roll if last three consecutive numbers differ by less than 1 percent.
// Rule 3: Re-roll if last five consecutive numbers increase
// Rule 4: Re-roll if last five consecutive numbers decrease
// Rule 5: Re-roll if last five consecutive numbers are all in the top half of the possible range
// Rule 6: Re-roll if last five consecutive numbers are all in the bottom half of the possible range
double h = low + high / 2;
while (
((rc >= 1) && (abs(r[rc-1] - candidate) <= 0.02*(high - low))) ||
((rc >= 2) && (abs(r[rc-2] - candidate) <= 0.01*(high - low))) ||
((rc >= 4 && r > r && r > r && r > r && r > r)) ||
((rc >= 4 && r < r && r < r < r < r && r < r)) ||
((rc >= 4) && r > h && r > h && r > h && r > h && r > h) ||
((rc >= 4) && r < h && r < h && r < h && r < h && r < h)
) { candidate = randRange(low, high); }

// Log and return the valid roll
r[rc] = candidate;
return candidate;
}
```