/* NetHack 3.6 rnd.c $NHDT-Date: 1524689470 2018/04/25 20:51:10 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.18 $ */ /* Copyright (c) 2004 by Robert Patrick Rankin */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" /* "Rand()"s definition is determined by [OS]conf.h */ #if defined(LINT) && defined(UNIX) /* rand() is long... */ extern int NDECL(rand); #define RND(x) (rand() % x) #else /* LINT */ #if defined(UNIX) || defined(RANDOM) #define RND(x) ((int) (Rand() % (long) (x))) #else /* Good luck: the bottom order bits are cyclic. */ #define RND(x) ((int) ((Rand() >> 3) % (x))) #endif #endif /* LINT */ /* 0 <= rn2(x) < x */ int rn2(x) register int x; { #ifdef BETA if (x <= 0) { impossible("rn2(%d) attempted", x); return 0; } x = RND(x); return x; #else return RND(x); #endif } /* 0 <= rnl(x) < x; sometimes subtracting Luck; good luck approaches 0, bad luck approaches (x-1) */ int rnl(x) register int x; { register int i, adjustment; #ifdef BETA if (x <= 0) { impossible("rnl(%d) attempted", x); return 0; } #endif adjustment = Luck; if (x <= 15) { /* for small ranges, use Luck/3 (rounded away from 0); also guard against architecture-specific differences of integer division involving negative values */ adjustment = (abs(adjustment) + 1) / 3 * sgn(adjustment); /* * 11..13 -> 4 * 8..10 -> 3 * 5.. 7 -> 2 * 2.. 4 -> 1 * -1,0,1 -> 0 (no adjustment) * -4..-2 -> -1 * -7..-5 -> -2 * -10..-8 -> -3 * -13..-11-> -4 */ } i = RND(x); if (adjustment && rn2(37 + abs(adjustment))) { i -= adjustment; if (i < 0) i = 0; else if (i >= x) i = x - 1; } return i; } /* 1 <= rnd(x) <= x */ int rnd(x) register int x; { #ifdef BETA if (x <= 0) { impossible("rnd(%d) attempted", x); return 1; } #endif x = RND(x) + 1; return x; } /* d(N,X) == NdX == dX+dX+...+dX N times; n <= d(n,x) <= (n*x) */ int d(n, x) register int n, x; { register int tmp = n; #ifdef BETA if (x < 0 || n < 0 || (x == 0 && n != 0)) { impossible("d(%d,%d) attempted", n, x); return 1; } #endif while (n--) tmp += RND(x); return tmp; /* Alea iacta est. -- J.C. */ } /* 1 <= rne(x) <= max(u.ulevel/3,5) */ int rne(x) register int x; { register int tmp, utmp; utmp = (u.ulevel < 15) ? 5 : u.ulevel / 3; tmp = 1; while (tmp < utmp && !rn2(x)) tmp++; return tmp; /* was: * tmp = 1; * while (!rn2(x)) * tmp++; * return min(tmp, (u.ulevel < 15) ? 5 : u.ulevel / 3); * which is clearer but less efficient and stands a vanishingly * small chance of overflowing tmp */ } /* rnz: everyone's favorite! */ int rnz(i) int i; { #ifdef LINT int x = i; int tmp = 1000; #else register long x = (long) i; register long tmp = 1000L; #endif tmp += rn2(1000); tmp *= rne(4); if (rn2(2)) { x *= tmp; x /= 1000; } else { x *= 1000; x /= tmp; } return (int) x; } /*rnd.c*/