Source:Rnd.c
From Wikihack
Below is the full text to src/rnd.c from NetHack 3.4.3. To link to a particular line, write [[rnd.c#line123]], for example.
This file contains the functions that power NetHack's RNG.
Contents |
[edit] License
1. /* SCCS Id: @(#)rnd.c 3.4 1996/02/07 */ 2. /* NetHack may be freely redistributed. See license for details. */ 3.
| The NetHack General Public License applies to screenshots, source code and other content from NetHack. |
[edit] Top of file
4. #include "hack.h" 5. 6. /* "Rand()"s definition is determined by [OS]conf.h */
See, for example, unixconf.h#line303.
7. #if defined(LINT) && defined(UNIX) /* rand() is long... */ 8. extern int NDECL(rand); 9. #define RND(x) (rand() % x) 10. #else /* LINT */ 11. # if defined(UNIX) || defined(RANDOM) 12. #define RND(x) (int)(Rand() % (long)(x)) 13. # else 14. /* Good luck: the bottom order bits are cyclic. */ 15. #define RND(x) (int)((Rand()>>3) % (x)) 16. # endif 17. #endif /* LINT */ 18.
The rest of the file does not worry about which implementation of Rand() is used, instead using the macro RND(x).
[edit] rn2
19. #ifdef OVL0 20. 21. int 22. rn2(x) /* 0 <= rn2(x) < x */ 23. register int x; 24. { 25. #ifdef DEBUG 26. if (x <= 0) { 27. impossible("rn2(%d) attempted", x); 28. return(0); 29. } 30. x = RND(x); 31. return(x); 32. #else 33. return(RND(x)); 34. #endif 35. } 36. 37. #endif /* OVL0 */
As line 22's comment suggests, rn2(x) returns an integer greater than or equal to zero and less than x.
This is used in the game in situations requiring a 50/50 chance of an event occurring: rn2(2) outputs 0 or 1 with equal probability.
[edit] rnl
38. #ifdef OVLB 39. 40. int 41. rnl(x) /* 0 <= rnl(x) < x; sometimes subtracting Luck */ 42. register int x; /* good luck approaches 0, bad luck approaches (x-1) */ 43. { 44. register int i; 45. 46. #ifdef DEBUG 47. if (x <= 0) { 48. impossible("rnl(%d) attempted", x); 49. return(0); 50. } 51. #endif 52. i = RND(x); 53. 54. if (Luck && rn2(50 - Luck)) { 55. i -= (x <= 15 && Luck >= -5 ? Luck/3 : Luck); 56. if (i < 0) i = 0; 57. else if (i >= x) i = x-1; 58. } 59. 60. return i; 61. } 62. 63. #endif /* OVLB */
rnl(x) is the same as rn2, with a chance of a proportion of your Luck being subtracted from the result. This means very lucky characters tend to see lower values and very unlucky characters tend to see higher values.
In-game, this is used to make saving throws against your Luck. For example, blessed armor has a saving throw against being eroded by a trap: if rnl(4) is zero, the armor escapes unscathed[1][2][3]:
First, i is a random integer from 0 to 3. A very lucky character (with +13 Luck) has a rn2(37) chance (36 in 37 ~= 97%) of this being reduced by Luck/3, which in this case rounds to 4. i cannot be reduced below 0, so it is set to 0. So the other 1 time in 37 there will be a 25% chance of i being 0. In total, that's a 145/148 chance (~=98%) that the armor will not be eroded.
In the worst case scenario (a very unlucky character with -13 Luck) there is a 251/252 (~=99.6%) of the armor being eroded.
Moral: keep your Luck high.
[edit] rnd
64. #ifdef OVL0 65. 66. int 67. rnd(x) /* 1 <= rnd(x) <= x */ 68. register int x; 69. { 70. #ifdef DEBUG 71. if (x <= 0) { 72. impossible("rnd(%d) attempted", x); 73. return(1); 74. } 75. x = RND(x)+1; 76. return(x); 77. #else 78. return(RND(x)+1); 79. #endif 80. } 81. 82. #endif /* OVL0 */
rnd(x) returns an integer from 1 to x, inclusive. This simulates the roll of an x-sided die.
[edit] d
83. #ifdef OVL1 84. 85. int 86. d(n,x) /* n <= d(n,x) <= (n*x) */ 87. register int n, x; 88. { 89. register int tmp = n; 90. 91. #ifdef DEBUG 92. if (x < 0 || n < 0 || (x == 0 && n != 0)) { 93. impossible("d(%d,%d) attempted", n, x); 94. return(1); 95. } 96. #endif 97. while(n--) tmp += RND(x); 98. return(tmp); /* Alea iacta est. -- J.C. */ 99. } 100. 101. #endif /* OVL1 */
d is NetHack's implementation of D notation from D&D. d(n,x) is equivalent to ndx (e.g. d(3,6) is like 3d6). This simulates the roll of n x-sided dice.
"Alea iacta est" is Latin for "the die is cast".
"J.C." refers to Julius Caesar, from whom this quote originates.
[edit] rne
102. #ifdef OVLB 103. 104. int 105. rne(x) 106. register int x; 107. { 108. register int tmp, utmp; 109. 110. utmp = (u.ulevel < 15) ? 5 : u.ulevel/3; 111. tmp = 1; 112. while (tmp < utmp && !rn2(x)) 113. tmp++; 114. return tmp; 115. 116. /* was: 117. * tmp = 1; 118. * while(!rn2(x)) tmp++; 119. * return(min(tmp,(u.ulevel < 15) ? 5 : u.ulevel/3)); 120. * which is clearer but less efficient and stands a vanishingly 121. * small chance of overflowing tmp 122. */ 123. } 124.
rne returns an exponentially weighted random integer from 1 to a number depending on your experience level. It is used in-game for deciding the enchantment of randomly generated items.
[edit] rnz
125. int 126. rnz(i) 127. int i; 128. { 129. #ifdef LINT 130. int x = i; 131. int tmp = 1000; 132. #else 133. register long x = i; 134. register long tmp = 1000; 135. #endif 136. tmp += rn2(1000); 137. tmp *= rne(4); 138. if (rn2(2)) { x *= tmp; x /= 1000; } 139. else { x *= 1000; x /= tmp; } 140. return((int)x); 141. } 142. 143. #endif /* OVLB */ 144. 145. /*rnd.c*/
rnz produces a very strange distribution and is used for calculating prayer timeouts, among other things.
[edit] See Also
hack.h#line291 - rn1(x,y) #define
