OSDN Git Service

upgrade to 3.6.1
[jnethack/source.git] / src / rnd.c
1 /* NetHack 3.6  rnd.c   $NHDT-Date: 1524689470 2018/04/25 20:51:10 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.18 $ */
2 /*      Copyright (c) 2004 by Robert Patrick Rankin               */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 /* "Rand()"s definition is determined by [OS]conf.h */
8 #if defined(LINT) && defined(UNIX) /* rand() is long... */
9 extern int NDECL(rand);
10 #define RND(x) (rand() % x)
11 #else /* LINT */
12 #if defined(UNIX) || defined(RANDOM)
13 #define RND(x) ((int) (Rand() % (long) (x)))
14 #else
15 /* Good luck: the bottom order bits are cyclic. */
16 #define RND(x) ((int) ((Rand() >> 3) % (x)))
17 #endif
18 #endif /* LINT */
19
20 /* 0 <= rn2(x) < x */
21 int
22 rn2(x)
23 register int x;
24 {
25 #ifdef BETA
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 /* 0 <= rnl(x) < x; sometimes subtracting Luck;
38    good luck approaches 0, bad luck approaches (x-1) */
39 int
40 rnl(x)
41 register int x;
42 {
43     register int i, adjustment;
44
45 #ifdef BETA
46     if (x <= 0) {
47         impossible("rnl(%d) attempted", x);
48         return 0;
49     }
50 #endif
51
52     adjustment = Luck;
53     if (x <= 15) {
54         /* for small ranges, use Luck/3 (rounded away from 0);
55            also guard against architecture-specific differences
56            of integer division involving negative values */
57         adjustment = (abs(adjustment) + 1) / 3 * sgn(adjustment);
58         /*
59          *       11..13 ->  4
60          *        8..10 ->  3
61          *        5.. 7 ->  2
62          *        2.. 4 ->  1
63          *       -1,0,1 ->  0 (no adjustment)
64          *       -4..-2 -> -1
65          *       -7..-5 -> -2
66          *      -10..-8 -> -3
67          *      -13..-11-> -4
68          */
69     }
70
71     i = RND(x);
72     if (adjustment && rn2(37 + abs(adjustment))) {
73         i -= adjustment;
74         if (i < 0)
75             i = 0;
76         else if (i >= x)
77             i = x - 1;
78     }
79     return i;
80 }
81
82 /* 1 <= rnd(x) <= x */
83 int
84 rnd(x)
85 register int x;
86 {
87 #ifdef BETA
88     if (x <= 0) {
89         impossible("rnd(%d) attempted", x);
90         return 1;
91     }
92 #endif
93     x = RND(x) + 1;
94     return x;
95 }
96
97 /* d(N,X) == NdX == dX+dX+...+dX N times; n <= d(n,x) <= (n*x) */
98 int
99 d(n, x)
100 register int n, x;
101 {
102     register int tmp = n;
103
104 #ifdef BETA
105     if (x < 0 || n < 0 || (x == 0 && n != 0)) {
106         impossible("d(%d,%d) attempted", n, x);
107         return 1;
108     }
109 #endif
110     while (n--)
111         tmp += RND(x);
112     return tmp; /* Alea iacta est. -- J.C. */
113 }
114
115 /* 1 <= rne(x) <= max(u.ulevel/3,5) */
116 int
117 rne(x)
118 register int x;
119 {
120     register int tmp, utmp;
121
122     utmp = (u.ulevel < 15) ? 5 : u.ulevel / 3;
123     tmp = 1;
124     while (tmp < utmp && !rn2(x))
125         tmp++;
126     return tmp;
127
128     /* was:
129      *  tmp = 1;
130      *  while (!rn2(x))
131      *    tmp++;
132      *  return min(tmp, (u.ulevel < 15) ? 5 : u.ulevel / 3);
133      * which is clearer but less efficient and stands a vanishingly
134      * small chance of overflowing tmp
135      */
136 }
137
138 /* rnz: everyone's favorite! */
139 int
140 rnz(i)
141 int i;
142 {
143 #ifdef LINT
144     int x = i;
145     int tmp = 1000;
146 #else
147     register long x = (long) i;
148     register long tmp = 1000L;
149 #endif
150
151     tmp += rn2(1000);
152     tmp *= rne(4);
153     if (rn2(2)) {
154         x *= tmp;
155         x /= 1000;
156     } else {
157         x *= 1000;
158         x /= tmp;
159     }
160     return (int) x;
161 }
162
163 /*rnd.c*/