# Rng.cpp code — bug? feature?

**URL:** <https://discourse.cataclysmdda.org/t/rng-cpp-code-bug-feature/702>\
**Category:** The Garage\
**Created:** [April 6, 2013, 5:36am UTC](https://discourse.cataclysmdda.org/t/rng-cpp-code-bug-feature/702 "2013-04-06T05:36:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Skyrunner](https://avatars.discourse-cdn.com/v4/letter/s/3ec8ea/32.png) [@Skyrunner](https://discourse.cataclysmdda.org/u/Skyrunner)\
**Post date:** [April 6, 2013, 5:36am UTC](https://discourse.cataclysmdda.org/t/rng-cpp-code-bug-feature/702/1 "2013-04-06T05:36:55Z")

</div>

The current code for rng.cpp is

[tt]long rng(long low, long high)  
{  
 return low + long((high - low + 1) \* double(rand() / double(RAND\_MAX + 1.0)));  
}[/tt]

Though apparently it hasn’t been a problem so far, adding the lines

[tt]//activating assert()  
#ifdef NDEBUG  
#undef NDEBUG  
#endif

#include [/tt]

and inserting [tt]assert (low \<= high)[/tt] causes

 ![](http://i.imgur.com/PKKFBux.png)

It seems that the game doesn’t follow the low/high conditions as it should. It potentially could cause problems with random numbers being out of range or stuff. I’m not sure how the algorithm works, currently, though it does seem to translate [tt]rand()[/tt] to the correct range then adding [tt]low[/tt] to the result. Adding

[tt]if (low \> high)  
{  
 long temp = high;  
high = low;  
low = temp;  
}[/tt]

presumably fixes the issue.

Stumbled upon this while trying to figure out how to mod Cataclysm. o\_O I’m not sure if it’s a bug or a feature. I wouldn’t even have known if not for boost.random’s assert, as I tried to use the uniform\_int\_distribution boost has instead of a rand()-using formula.

---

<div class="post-metadata">

**Author:** ![KA101](https://avatars.discourse-cdn.com/v4/letter/k/278dde/32.png) [@KA101](https://discourse.cataclysmdda.org/u/KA101)\
**Post date:** [April 7, 2013, 5:36am UTC](https://discourse.cataclysmdda.org/t/rng-cpp-code-bug-feature/702/2 "2013-04-07T05:36:23Z")

</div>

Huh. I know that one high-level encounter doesn’t always spawn its participants like it seems it should. Though there’s certainly other possible reasons for that (probably including my misreading its code) this is certainly interesting.

---

<div class="post-metadata">

**Author:** ![Skyrunner](https://avatars.discourse-cdn.com/v4/letter/s/3ec8ea/32.png) [@Skyrunner](https://discourse.cataclysmdda.org/u/Skyrunner)\
**Post date:** [April 7, 2013, 11:39am UTC](https://discourse.cataclysmdda.org/t/rng-cpp-code-bug-feature/702/3 "2013-04-07T11:39:27Z")

</div>

A better investigation turned out that the assert fail only happens once, when you make a random character. The numbers involved are 0 and -1.

---

<div class="post-metadata">

**Author:** ![oohara](https://avatars.discourse-cdn.com/v4/letter/o/dbc845/32.png) [@oohara](https://discourse.cataclysmdda.org/u/oohara)\
**Post date:** [June 19, 2013, 3:16pm UTC](https://discourse.cataclysmdda.org/t/rng-cpp-code-bug-feature/702/4 "2013-06-19T15:16:28Z")

</div>

I ran the version 0.5 stable with the assert.  
Here is what I found:

— a/overmap.cpp  
+++ b/overmap.cpp  
@@ -810,7 +810,7 @@

```
else if (ter(i, j, z + 1) == ot_lab_core ||
         (z == -1 && ter(i, j, z + 1) == ot_lab_stairs))

```

- lab\_points.push\_back(city(i, j, rng(1, 5 + z)));

- lab\_points.push\_back(city(i, j, 1));

```
else if (ter(i, j, z + 1) == ot_lab_stairs)
 ter(i, j, z) = ot_lab;

```

— a/mapgen.cpp  
+++ b/mapgen.cpp  
@@ -205,7 +205,8 @@  
}  
draw\_map(terrain\_type, t\_north, t\_east, t\_south, t\_west, t\_above, turn, g, density);

- if ( one\_in( oterlist[terrain\_type].embellishments.chance ))

- // one\_in(chance) returns true if chance \<= 1

- if (oterlist[terrain\_type].embellishments.chance \> 0 && one\_in( oterlist[terrain\_type].embellishments.chance ))  
add\_extra( random\_map\_extra( oterlist[terrain\_type].embellishments ), g);

- tw = rng(3, 10);

- tw = rng(3, 8);  
bw = SEEY \* 2 - 1 - rng(0, 3);

- cw = bw - rng(3, 5);

- cw = bw - rng(3, 4);  
for (int i = 0; i \< SEEX \* 2; i++) {  
for (int j = 0; j \< SEEY \* 2; j++) {  
if (((j == tw || j == bw) && i \>= lw && i \<= rw) ||  
@@ -10360,6 +10361,20 @@  
debugmsg(“map::place\_items() called for an empty items list (list #%d)”, loc);  
return;  
}

- if (x1 \> x2)

- {

- int temp;

- temp = x1;

- x1 = x2;

- x2 = temp;

- }

- if (y1 \> y2)

- {

- int temp;

- temp = y1;

- y1 = y2;

- y2 = temp;

- }

int dice(int number, int sides)  
{

- // this happens when the player uses a crowbar without the mechanics skill
- if (sides \<= 0)
- return 0;
- int ret = 0;  
for (int i = 0; i \< number; i++)  
ret += rng(1, sides);
