Wikia

Wikihack

Source:Rnd.c

2,032pages on
this wiki
Talk0

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.

LicenseEdit

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.

Top of fileEdit

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).

rn2Edit

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.

rnlEdit

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.

rndEdit

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.

dEdit

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 */

File:3d6.svg

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.

rneEdit

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.  

File:Rne3.svg

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.

rnzEdit

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*/

File:Rnz100.svg

rnz produces a very strange distribution and is used for calculating prayer timeouts, among other things.

See Also Edit

hack.h#line291 - rn1(x,y) #define

Source code referencesEdit

  1. trap.c#line162
  2. trap.c#line2666
  3. trap.c#line2723

Around Wikia's network

Random Wiki