Difference between revisions of "Source:NetHack 3.4.3/src/rnd.c"
(Automated source code upload) |
(90% annotated; somebody learned in rnz() will need to finish it...) |
||
Line 1: | Line 1: | ||
+ | Below is the full text to src/rnd.c from NetHack 3.4.3. To link to a particular line, write [[rnd.c#line123|<nowiki>[[rnd.c#line123]]</nowiki>]], for example. | ||
+ | |||
+ | This file contains the functions that power NetHack's [[RNG]] | ||
+ | |||
+ | ==License== | ||
− | |||
<span id="line1">1. /* SCCS Id: @(#)rnd.c 3.4 1996/02/07 */</span> | <span id="line1">1. /* SCCS Id: @(#)rnd.c 3.4 1996/02/07 */</span> | ||
<span id="line2">2. /* NetHack may be freely redistributed. See license for details. */</span> | <span id="line2">2. /* NetHack may be freely redistributed. See license for details. */</span> | ||
Line 7: | Line 11: | ||
{{NGPL}} | {{NGPL}} | ||
+ | |||
+ | ==Top of file== | ||
<span id="line5">5. </span> | <span id="line5">5. </span> | ||
<span id="line6">6. /* "Rand()"s definition is determined by [OS]conf.h */</span> | <span id="line6">6. /* "Rand()"s definition is determined by [OS]conf.h */</span> | ||
+ | |||
+ | See, for example, [[unixconf.h#line303]]. | ||
+ | |||
<span id="line7">7. #if defined(LINT) && defined(UNIX) /* rand() is long... */</span> | <span id="line7">7. #if defined(LINT) && defined(UNIX) /* rand() is long... */</span> | ||
<span id="line8">8. extern int NDECL(rand);</span> | <span id="line8">8. extern int NDECL(rand);</span> | ||
Line 22: | Line 31: | ||
<span id="line17">17. #endif /* LINT */</span> | <span id="line17">17. #endif /* LINT */</span> | ||
<span id="line18">18. </span> | <span id="line18">18. </span> | ||
+ | |||
+ | |||
+ | The rest of the file does not worry about which implementation of Rand() is used, instead using the macro RND(x). | ||
+ | |||
+ | ==rn2== | ||
+ | |||
<span id="line19">19. #ifdef OVL0</span> | <span id="line19">19. #ifdef OVL0</span> | ||
<span id="line20">20. </span> | <span id="line20">20. </span> | ||
Line 41: | Line 56: | ||
<span id="line36">36. </span> | <span id="line36">36. </span> | ||
<span id="line37">37. #endif /* OVL0 */</span> | <span id="line37">37. #endif /* OVL0 */</span> | ||
+ | |||
+ | |||
+ | As line 22's comment suggests, rn2(x) returns an integer greater than 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. | ||
+ | |||
+ | ==rnl== | ||
+ | |||
<span id="line38">38. #ifdef OVLB</span> | <span id="line38">38. #ifdef OVLB</span> | ||
<span id="line39">39. </span> | <span id="line39">39. </span> | ||
Line 67: | Line 90: | ||
<span id="line62">62. </span> | <span id="line62">62. </span> | ||
<span id="line63">63. #endif /* OVLB */</span> | <span id="line63">63. #endif /* OVLB */</span> | ||
+ | |||
+ | 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<ref>[[trap.c#line162]]</ref><ref>[[trap.c#line2666]]</ref><ref>[[trap.c#line2723]]</ref>: | ||
+ | |||
+ | 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. | ||
+ | |||
+ | ==rnd== | ||
+ | |||
<span id="line64">64. #ifdef OVL0</span> | <span id="line64">64. #ifdef OVL0</span> | ||
<span id="line65">65. </span> | <span id="line65">65. </span> | ||
Line 86: | Line 122: | ||
<span id="line81">81. </span> | <span id="line81">81. </span> | ||
<span id="line82">82. #endif /* OVL0 */</span> | <span id="line82">82. #endif /* OVL0 */</span> | ||
+ | |||
+ | rnd(x) returns an integer from 1 to x, inclusive. This simulates the roll of an x-sided die. | ||
+ | |||
+ | ==d== | ||
+ | |||
<span id="line83">83. #ifdef OVL1</span> | <span id="line83">83. #ifdef OVL1</span> | ||
<span id="line84">84. </span> | <span id="line84">84. </span> | ||
Line 105: | Line 146: | ||
<span id="line100">100. </span> | <span id="line100">100. </span> | ||
<span id="line101">101. #endif /* OVL1 */</span> | <span id="line101">101. #endif /* OVL1 */</span> | ||
+ | |||
+ | 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". | ||
+ | |||
+ | ==rne== | ||
+ | |||
<span id="line102">102. #ifdef OVLB</span> | <span id="line102">102. #ifdef OVLB</span> | ||
<span id="line103">103. </span> | <span id="line103">103. </span> | ||
Line 128: | Line 176: | ||
<span id="line123">123. }</span> | <span id="line123">123. }</span> | ||
<span id="line124">124. </span> | <span id="line124">124. </span> | ||
+ | |||
+ | 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. | ||
+ | |||
+ | ==rnz== | ||
+ | |||
<span id="line125">125. int</span> | <span id="line125">125. int</span> | ||
<span id="line126">126. rnz(i)</span> | <span id="line126">126. rnz(i)</span> | ||
Line 149: | Line 202: | ||
<span id="line144">144. </span> | <span id="line144">144. </span> | ||
<span id="line145">145. /*rnd.c*/</span> | <span id="line145">145. /*rnd.c*/</span> | ||
+ | |||
+ | rnz produces a very strange distribution and is used for calculating prayer timeouts, among other things. | ||
+ | |||
+ | ==Source code references== | ||
+ | |||
+ | <references/> | ||
+ | |||
[[Category:source code]] | [[Category:source code]] |
Revision as of 15:38, 19 July 2006
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
License
1. /* SCCS Id: @(#)rnd.c 3.4 1996/02/07 */ 2. /* NetHack may be freely redistributed. See license for details. */ 3. 4. #include "hack.h"
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
Top of file
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).
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 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.
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.
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.
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".
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.
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.