diff --git a/include/config.h b/include/config.h index d59a82af5..3177512e1 100644 --- a/include/config.h +++ b/include/config.h @@ -556,6 +556,7 @@ typedef unsigned char uchar; #endif +#define USE_ISAAC64 /* Use cross-plattform, bundled RNG */ /* End of Section 4 */ diff --git a/include/decl.h b/include/decl.h index 66bfd74c1..eb3c904c4 100644 --- a/include/decl.h +++ b/include/decl.h @@ -220,6 +220,7 @@ E NEARDATA boolean mrg_to_wielded; E NEARDATA boolean defer_see_monsters; E NEARDATA boolean in_steed_dismounting; +E NEARDATA boolean has_strong_rngseed; E const int shield_static[]; diff --git a/include/extern.h b/include/extern.h index 947546839..7e48246f5 100644 --- a/include/extern.h +++ b/include/extern.h @@ -925,7 +925,8 @@ E char *FDECL(strstri, (const char *, const char *)); #endif E boolean FDECL(fuzzymatch, (const char *, const char *, const char *, BOOLEAN_P)); -E void NDECL(setrandom); +E void NDECL(init_random); +E void NDECL(reseed_random); E time_t NDECL(getnow); E int NDECL(getyear); #if 0 @@ -2103,6 +2104,10 @@ E void FDECL(genl_outrip, (winid, int, time_t)); /* ### rnd.c ### */ +#ifdef USE_ISAAC64 +E void FDECL(init_isaac64, (unsigned long)); +E long NDECL(nhrand); +#endif E int FDECL(rn2, (int)); E int FDECL(rn2_on_display_rng, (int)); E int FDECL(rnl, (int)); diff --git a/include/integer.h b/include/integer.h index 044da028d..9f16a592d 100644 --- a/include/integer.h +++ b/include/integer.h @@ -7,35 +7,47 @@ #ifndef INTEGER_H #define INTEGER_H -#if defined(__STDC__) && __STDC__ >= 199101L - +#if defined(__STDC__) && __STDC_VERSION__ >= 199101L /* The compiler claims to conform to C99. Use stdint.h */ #include +#define SKIP_STDINT_WORKAROUND +#else +# if defined(HAS_STDINT_H) +/* Some compilers have stdint.h but don't conform to all of C99. */ +#include +#define SKIP_STDINT_WORKAROUND +# endif +#endif + +#ifndef SKIP_STDINT_WORKAROUND /* !C99 */ +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; + +#if defined(__WATCOMC__) && !defined(__386__) +/* Open Watcom providing a 16 bit build for MS-DOS or OS/2 */ +/* int is 16 bits; use long for 32 bits */ +typedef long int32_t; +typedef unsigned long uint32_t; +#else +/* Otherwise, assume either a 32- or 64-bit compiler */ +/* long may be 64 bits; use int for 32 bits */ +typedef int int32_t; +typedef unsigned int uint32_t; +#endif + +typedef long long int64_t; +typedef unsigned long long uint64_t; + +#endif /* !C99 */ + +/* Provide uint8, int16, uint16, int32, uint32, int64 and uint64 */ typedef uint8_t uint8; typedef int16_t int16; typedef uint16_t uint16; typedef int32_t int32; typedef uint32_t uint32; - -#else /* !C99 */ - -/* Provide uint8, int16, uint16, int32 and uint32 */ -typedef unsigned char uint8; -typedef short int16; -typedef unsigned short uint16; - -#if defined(__WATCOMC__) && !defined(__386__) -/* Open Watcom providing a 16 bit build for MS-DOS or OS/2 */ -/* int is 16 bits; use long for 32 bits */ -typedef long int32; -typedef unsigned long uint32; -#else -/* Otherwise, assume either a 32- or 64-bit compiler */ -/* long may be 64 bits; use int for 32 bits */ -typedef int int32; -typedef unsigned int uint32; -#endif - -#endif /* !C99 */ +typedef int64_t int64; +typedef uint64_t uint64; #endif /* INTEGER_H */ diff --git a/include/isaac64.h b/include/isaac64.h new file mode 100644 index 000000000..6c9b45b52 --- /dev/null +++ b/include/isaac64.h @@ -0,0 +1,89 @@ +/* CC0 (Public domain) - see http://creativecommons.org/publicdomain/zero/1.0/ for details */ +#if !defined(_isaac64_H) +# define _isaac64_H (1) +# include + + + +typedef struct isaac64_ctx isaac64_ctx; + + + +#define ISAAC64_SZ_LOG (8) +#define ISAAC64_SZ (1< #define USE_STDARG -#ifdef RANDOM + /* Use the high quality random number routines. */ -#define Rand() random() +#ifdef USE_ISAAC64 +#undef RANDOM #else +#define RANDOM +#define Rand() random() +#endif + +/* Fall back to C's if nothing else, but this really isn't acceptable */ +#if !defined(USE_ISAAC64) && !defined(RANDOM) #define Rand() rand() #endif diff --git a/include/os2conf.h b/include/os2conf.h index f033ef584..fd625512a 100644 --- a/include/os2conf.h +++ b/include/os2conf.h @@ -78,11 +78,12 @@ #include /* the high quality random number routines */ - -#ifdef RANDOM -#define Rand() random() -#else -#define Rand() rand() +#ifndef USE_ISAAC64 +# ifdef RANDOM +# define Rand() random() +# else +# define Rand() rand() +# endif #endif /* file creation mask */ diff --git a/include/pcconf.h b/include/pcconf.h index c5b46bea9..fb210b8ca 100644 --- a/include/pcconf.h +++ b/include/pcconf.h @@ -236,11 +236,13 @@ #include #endif -#ifdef RANDOM -/* Use the high quality random number routines. */ -#define Rand() random() -#else -#define Rand() rand() +/* the high quality random number routines */ +#ifndef USE_ISAAC64 +# ifdef RANDOM +# define Rand() random() +# else +# define Rand() rand() +# endif #endif #ifndef TOS diff --git a/include/unixconf.h b/include/unixconf.h index 0c42c6040..781e3563e 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -347,11 +347,14 @@ #endif /* Use the high quality random number routines. */ -#if defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) \ +/* the high quality random number routines */ +#ifndef USE_ISAAC64 +# if defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) \ || defined(RANDOM) || defined(__APPLE__) -#define Rand() random() -#else -#define Rand() lrand48() +# define Rand() random() +# else +# define Rand() lrand48() +# endif #endif #ifdef TIMED_DELAY @@ -408,5 +411,18 @@ # define RUNTIME_PASTEBUF_SUPPORT #endif +/* + * /dev/random is blocking on Linux, so there we default to /dev/urandom which + * should still be good enough. + * BSD systems usually have /dev/random that is supposed to be used. + */ +#ifdef LINUX +# define DEV_RANDOM "/dev/urandom" +#else +# ifdef BSD +# define DEV_RANDOM "/dev/random" +# endif +#endif + #endif /* UNIXCONF_H */ #endif /* UNIX */ diff --git a/include/vmsconf.h b/include/vmsconf.h index 7674e8558..40cde73a0 100644 --- a/include/vmsconf.h +++ b/include/vmsconf.h @@ -243,17 +243,19 @@ typedef __mode_t mode_t; #define rindex strrchr /* Use the high quality random number routines. */ -#if defined(RANDOM) -#define Rand() random() +#ifndef USE_ISAAC64 +# if defined(RANDOM) +# define Rand() random() /* VMS V7 adds these entry points to DECC$SHR; stick with the nethack-supplied code to avoid having to deal with version-specific conditionalized builds */ -#define random nh_random -#define srandom nh_srandom -#define initstate nh_initstate -#define setstate nh_setstate -#else -#define Rand() rand() +# define random nh_random +# define srandom nh_srandom +# define initstate nh_initstate +# define setstate nh_setstate +# else +# define Rand() rand() +# endif #endif #ifndef __GNUC__ diff --git a/include/wceconf.h b/include/wceconf.h index 7ab03f672..dcc7b6f95 100644 --- a/include/wceconf.h +++ b/include/wceconf.h @@ -141,11 +141,14 @@ #define index strchr #define rindex strrchr #define USE_STDARG -#ifdef RANDOM + /* Use the high quality random number routines. */ -#define Rand() random() -#else -#define Rand() rand() +#ifndef USE_ISAAC64 +# ifdef RANDOM +# define Rand() random() +# else +# define Rand() rand() +# endif #endif #define FCMASK 0660 /* file creation mask */ diff --git a/src/decl.c b/src/decl.c index 3e9fb82cc..2849418e6 100644 --- a/src/decl.c +++ b/src/decl.c @@ -120,6 +120,7 @@ NEARDATA boolean mrg_to_wielded = FALSE; /* weapon picked is merged with wielded one */ NEARDATA boolean in_steed_dismounting = FALSE; +NEARDATA boolean has_strong_rngseed = FALSE; NEARDATA coord bhitpos = DUMMY; NEARDATA coord doors[DOORMAX] = { DUMMY }; diff --git a/src/do.c b/src/do.c index e069c3ac6..ad2e3045d 100644 --- a/src/do.c +++ b/src/do.c @@ -1420,6 +1420,7 @@ boolean at_stairs, falling, portal; /* we'll reach here if running in wizard mode */ error("Cannot continue this game."); } + reseed_random(); minit(); /* ZEROCOMP */ getlev(fd, hackpid, new_ledger, FALSE); (void) nhclose(fd); diff --git a/src/hacklib.c b/src/hacklib.c index d0c6915f0..60f492b37 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -51,6 +51,8 @@ boolean fuzzymatch (const char *, const char *, const char *, boolean) void setrandom (void) + void init_random (void) + void reseed_random (void) time_t getnow (void) int getyear (void) char * yymmdd (time_t) @@ -848,44 +850,59 @@ extern struct tm *FDECL(localtime, (time_t *)); #endif STATIC_DCL struct tm *NDECL(getlt); -void -setrandom() +/* Sets the seed for the random number generator */ +static void +set_random(unsigned long seed) { - unsigned long seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ - -#if defined(UNIX) || defined(VMS) - { - unsigned long pid = (unsigned long) getpid(); - - /* Quick dirty band-aid to prevent PRNG prediction */ - if (pid) { - if (!(pid & 3L)) - pid -= 1L; - seed *= pid; - } - } -#endif - +#ifdef USE_ISAAC64 + init_isaac64(seed); +#else /* the types are different enough here that sweeping the different * routine names into one via #defines is even more confusing */ -#ifdef RANDOM /* srandom() from sys/share/random.c */ +# ifdef RANDOM /* srandom() from sys/share/random.c */ srandom((unsigned int) seed); -#else -#if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ +# else +# if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ || defined(CYGWIN32) /* system srandom() */ -#if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) +# if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) (void) -#endif +# endif srandom((int) seed); -#else -#ifdef UNIX /* system srand48() */ +# else +# ifdef UNIX /* system srand48() */ srand48((long) seed); -#else /* poor quality system routine */ +# else /* poor quality system routine */ srand((int) seed); +# endif +# endif +# endif #endif -#endif -#endif +} + +/* An appropriate version of this must always be provided in + port-specific code somewhere. It returns a number suitable + as seed for the random number generator */ +extern unsigned long NDECL(sys_random_seed); + +/* + * Initializes the random number generator. + * Only call once. + */ +void +init_random() +{ + set_random(sys_random_seed()); +} + +/* Reshuffles the random number generator. */ +void +reseed_random() +{ + /* only reseed if we are certain that the seed generation is unguessable + * by the players. */ + if (has_strong_rngseed) + init_random(); } time_t diff --git a/src/isaac64.c b/src/isaac64.c new file mode 100644 index 000000000..6928ff72b --- /dev/null +++ b/src/isaac64.c @@ -0,0 +1,161 @@ +/*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 + CC0 (Public domain) - see http://creativecommons.org/publicdomain/zero/1.0/ for details + Based on the public domain ISAAC implementation by Robert J. Jenkins Jr.*/ +#include +#include +#include "isaac64.h" + +#define ISAAC64_MASK ((uint64_t)0xFFFFFFFFFFFFFFFFULL) + +#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) +#define HAS_INLINE +#endif + +/* Extract ISAAC64_SZ_LOG bits (starting at bit 3). */ +#ifdef HAS_INLINE +static inline uint32_t lower_bits(uint64_t x) +#else +static uint32_t lower_bits(uint64_t x) +#endif +{ + return (x & ((ISAAC64_SZ-1) << 3)) >>3; +} + +/* Extract next ISAAC64_SZ_LOG bits (starting at bit ISAAC64_SZ_LOG+2). */ +#ifdef HAS_INLINE +static inline uint32_t upper_bits(uint64_t y) +#else +static uint32_t upper_bits(uint64_t y) +#endif +{ + return (y >> (ISAAC64_SZ_LOG+3)) & (ISAAC64_SZ-1); +} + +static void isaac64_update(isaac64_ctx *_ctx){ + uint64_t *m; + uint64_t *r; + uint64_t a; + uint64_t b; + uint64_t x; + uint64_t y; + int i; + m=_ctx->m; + r=_ctx->r; + a=_ctx->a; + b=_ctx->b+(++_ctx->c); + for(i=0;i>5)+m[i+ISAAC64_SZ/2]; + m[i]=y=m[lower_bits(x)]+a+b; + r[i]=b=m[upper_bits(y)]+x; + x=m[++i]; + a=(a^a<<12)+m[i+ISAAC64_SZ/2]; + m[i]=y=m[lower_bits(x)]+a+b; + r[i]=b=m[upper_bits(y)]+x; + x=m[++i]; + a=(a^a>>33)+m[i+ISAAC64_SZ/2]; + m[i]=y=m[lower_bits(x)]+a+b; + r[i]=b=m[upper_bits(y)]+x; + } + for(i=ISAAC64_SZ/2;i>5)+m[i-ISAAC64_SZ/2]; + m[i]=y=m[lower_bits(x)]+a+b; + r[i]=b=m[upper_bits(y)]+x; + x=m[++i]; + a=(a^a<<12)+m[i-ISAAC64_SZ/2]; + m[i]=y=m[lower_bits(x)]+a+b; + r[i]=b=m[upper_bits(y)]+x; + x=m[++i]; + a=(a^a>>33)+m[i-ISAAC64_SZ/2]; + m[i]=y=m[lower_bits(x)]+a+b; + r[i]=b=m[upper_bits(y)]+x; + } + _ctx->b=b; + _ctx->a=a; + _ctx->n=ISAAC64_SZ; +} + +static void isaac64_mix(uint64_t _x[8]){ + static const unsigned char SHIFT[8]={9,9,23,15,14,20,17,14}; + int i; + for(i=0;i<8;i++){ + _x[i]-=_x[(i+4)&7]; + _x[(i+5)&7]^=_x[(i+7)&7]>>SHIFT[i]; + _x[(i+7)&7]+=_x[i]; + i++; + _x[i]-=_x[(i+4)&7]; + _x[(i+5)&7]^=_x[(i+7)&7]<a=_ctx->b=_ctx->c=0; + memset(_ctx->r,0,sizeof(_ctx->r)); + isaac64_reseed(_ctx,_seed,_nseed); +} + +void isaac64_reseed(isaac64_ctx *_ctx,const unsigned char *_seed,int _nseed){ + uint64_t *m; + uint64_t *r; + uint64_t x[8]; + int i; + int j; + m=_ctx->m; + r=_ctx->r; + if(_nseed>ISAAC64_SEED_SZ_MAX)_nseed=ISAAC64_SEED_SZ_MAX; + for(i=0;i<_nseed>>3;i++){ + r[i]^=(uint64_t)_seed[i<<3|7]<<56|(uint64_t)_seed[i<<3|6]<<48| + (uint64_t)_seed[i<<3|5]<<40|(uint64_t)_seed[i<<3|4]<<32| + (uint64_t)_seed[i<<3|3]<<24|(uint64_t)_seed[i<<3|2]<<16| + (uint64_t)_seed[i<<3|1]<<8|_seed[i<<3]; + } + _nseed-=i<<3; + if(_nseed>0){ + uint64_t ri; + ri=_seed[i<<3]; + for(j=1;j<_nseed;j++)ri|=(uint64_t)_seed[i<<3|j]<<(j<<3); + r[i++]^=ri; + } + x[0]=x[1]=x[2]=x[3]=x[4]=x[5]=x[6]=x[7]=(uint64_t)0x9E3779B97F4A7C13ULL; + for(i=0;i<4;i++)isaac64_mix(x); + for(i=0;in)isaac64_update(_ctx); + return _ctx->r[--_ctx->n]; +} + +uint64_t isaac64_next_uint(isaac64_ctx *_ctx,uint64_t _n){ + uint64_t r; + uint64_t v; + uint64_t d; + do{ + r=isaac64_next_uint64(_ctx); + v=r%_n; + d=r-v; + } + while(((d+_n-1)&ISAAC64_MASK)>= 8; + } + + isaac64_init(&rng_state, new_rng_state, sizeof(seed)); +} + +static int +RND(int x) +{ + return (isaac64_next_uint64(&rng_state) % x); +} + +#else /* "Rand()"s definition is determined by [OS]conf.h */ #if defined(LINT) && defined(UNIX) /* rand() is long... */ extern int NDECL(rand); @@ -16,6 +41,7 @@ extern int NDECL(rand); #define RND(x) ((int) ((Rand() >> 3) % (x))) #endif #endif /* LINT */ +#endif /* 0 <= rn2(x) < x */ int diff --git a/src/rumors.c b/src/rumors.c index c8d05be32..870f19342 100644 --- a/src/rumors.c +++ b/src/rumors.c @@ -125,12 +125,12 @@ boolean exclude_cookie; case 2: /*(might let a bogus input arg sneak thru)*/ case 1: beginning = (long) true_rumor_start; - tidbit = Rand() % true_rumor_size; + tidbit = rn2(true_rumor_size); break; case 0: /* once here, 0 => false rather than "either"*/ case -1: beginning = (long) false_rumor_start; - tidbit = Rand() % false_rumor_size; + tidbit = rn2(false_rumor_size); break; default: impossible("strange truth value for rumor"); diff --git a/sys/msdos/msdos.c b/sys/msdos/msdos.c index d943b864d..69f994be6 100644 --- a/sys/msdos/msdos.c +++ b/sys/msdos/msdos.c @@ -519,4 +519,15 @@ unsigned setvalue; return (regs.x.dx); } +unsigned long +sys_random_seed(VOID_ARGS) +{ + unsigned long ourseed = 0UL; + time_t datetime = 0; + + (void) time(&datetime); + ourseed = (unsigned long) datetime; + return ourseed; +} + #endif /* MSDOS */ diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src index 5548ed479..c6f25e029 100644 --- a/sys/unix/Makefile.src +++ b/sys/unix/Makefile.src @@ -441,9 +441,9 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ botl.c cmd.c dbridge.c decl.c detect.c dig.c display.c dlb.c do.c \ do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c drawing.c \ dungeon.c eat.c end.c engrave.c exper.c explode.c extralev.c \ - files.c fountain.c hack.c hacklib.c invent.c light.c lock.c \ - mail.c makemon.c mapglyph.c mcastu.c mhitm.c mhitu.c minion.c \ - mklev.c mkmap.c \ + files.c fountain.c hack.c hacklib.c invent.c isaac64.c light.c \ + lock.c mail.c makemon.c mapglyph.c mcastu.c mhitm.c mhitu.c \ + minion.c mklev.c mkmap.c \ mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c monst.c \ mplayer.c mthrowu.c muse.c music.c o_init.c objects.c objnam.c \ options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \ @@ -508,8 +508,8 @@ HOBJ = $(FIRSTOBJ) allmain.o alloc.o apply.o artifact.o attrib.o ball.o \ bones.o botl.o cmd.o dbridge.o decl.o detect.o dig.o display.o dlb.o \ do.o do_name.o do_wear.o dog.o dogmove.o dokick.o dothrow.o \ drawing.o dungeon.o eat.o end.o engrave.o exper.o explode.o \ - extralev.o files.o fountain.o hack.o hacklib.o invent.o light.o \ - lock.o mail.o makemon.o mapglyph.o mcastu.o mhitm.o mhitu.o \ + extralev.o files.o fountain.o hack.o hacklib.o invent.o isaac64.o \ + light.o lock.o mail.o makemon.o mapglyph.o mcastu.o mhitm.o mhitu.o \ minion.o mklev.o mkmap.o \ mkmaze.o mkobj.o mkroom.o mon.o mondata.o monmove.o \ mplayer.o mthrowu.o muse.o music.o o_init.o objnam.o options.o \ @@ -1013,6 +1013,7 @@ fountain.o: fountain.c $(HACK_H) hack.o: hack.c $(HACK_H) hacklib.o: hacklib.c $(HACK_H) invent.o: invent.c $(HACK_H) +isaac64.o: isaac64.c ../include/isaac64.h ../include/integer.h light.o: light.c $(HACK_H) ../include/lev.h lock.o: lock.c $(HACK_H) mail.o: mail.c $(HACK_H) ../include/mail.h diff --git a/sys/unix/hints/macosx10.10 b/sys/unix/hints/macosx10.10 index 85d4b63fa..e53a80d77 100644 --- a/sys/unix/hints/macosx10.10 +++ b/sys/unix/hints/macosx10.10 @@ -69,7 +69,7 @@ CC=gcc # #CFLAGS+=-W -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -DGCC_WARN -CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic +CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic -Wno-long-long # As of LLVM build 2336.1.00, this gives dozens of spurious messages, so # leave it out by default. #CFLAGS+=-Wunreachable-code diff --git a/sys/unix/hints/macosx10.14 b/sys/unix/hints/macosx10.14 index 2255ddb9e..c5e5a0cf1 100644 --- a/sys/unix/hints/macosx10.14 +++ b/sys/unix/hints/macosx10.14 @@ -69,7 +69,7 @@ CC=gcc # #CFLAGS+=-W -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -DGCC_WARN -CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic +CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic -Wno-long-long # As of LLVM build 2336.1.00, this gives dozens of spurious messages, so # leave it out by default. #CFLAGS+=-Wunreachable-code diff --git a/sys/unix/hints/macosx10.5 b/sys/unix/hints/macosx10.5 index 668b6b2b5..f6d9e5483 100644 --- a/sys/unix/hints/macosx10.5 +++ b/sys/unix/hints/macosx10.5 @@ -53,7 +53,7 @@ GAMEGRP = games #WANT_SOURCE_INSTALL=1 #CC=gcc -W -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -DGCC_WARN -CC=gcc -Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic +CC=gcc -Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic -Wno-long-long # # You shouldn't need to change anything below here. diff --git a/sys/unix/hints/macosx10.7 b/sys/unix/hints/macosx10.7 index cc9216884..776cb4b81 100644 --- a/sys/unix/hints/macosx10.7 +++ b/sys/unix/hints/macosx10.7 @@ -63,7 +63,7 @@ CC=gcc # #CFLAGS+=-W -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -DGCC_WARN -CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic +CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic -Wno-long-long # As of LLVM build 2336.1.00, this gives dozens of spurious messages, so # leave it out by default. #CFLAGS+=-Wunreachable-code diff --git a/sys/unix/hints/macosx10.8 b/sys/unix/hints/macosx10.8 index 6a1f69d4b..87d0e8305 100644 --- a/sys/unix/hints/macosx10.8 +++ b/sys/unix/hints/macosx10.8 @@ -70,7 +70,7 @@ CC=gcc # #CFLAGS+=-W -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -DGCC_WARN -CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic +CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic -Wno-long-long # As of LLVM build 2336.1.00, this gives dozens of spurious messages, so # leave it out by default. #CFLAGS+=-Wunreachable-code diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index f798fa163..1d6500b68 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -765,4 +765,36 @@ error: } #endif +unsigned long +sys_random_seed() +{ + unsigned long seed; + unsigned long pid = (unsigned long) getpid(); + boolean no_seed = TRUE; +#ifdef DEV_RANDOM + FILE *fptr = NULL; + + fptr = fopen(DEV_RANDOM, "r"); + if (fptr) { + fread(&seed, sizeof(long), 1, fptr); + has_strong_rngseed = TRUE; /* decl.c */ + no_seed = FALSE; + fclose(fptr); + } else { + /* leaves clue, doesn't exit */ + paniclog("sys_random_seed", "falling back to weak seed"); + } +#endif + if (no_seed) { + seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ + /* Quick dirty band-aid to prevent PRNG prediction */ + if (pid) { + if (!(pid & 3L)) + pid -= 1L; + seed *= pid; + } + } + return seed; +} + /*unixmain.c*/ diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index 75f321cb0..98f04be23 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -465,4 +465,20 @@ wd_message() You("are in non-scoring explore/discovery mode."); } +unsigned long +sys_random_seed() +{ + unsigned long seed; + unsigned long pid = (unsigned long) getpid(); + + seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ + /* Quick dirty band-aid to prevent PRNG prediction */ + if (pid) { + if (!(pid & 3L)) + pid -= 1L; + seed *= pid; + } + return seed; +} + /*vmsmain.c*/ diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 6dcd10d4d..97001da6e 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -129,9 +129,13 @@ OBJ = o # (see pcconf.h). Set to nothing if not used. # -RANDOM = $(OBJ)\random.o +RANDOM = $(OBJ)\isaac64.o +#RANDOM = $(OBJ)\random.o #RANDOM = - +BCRYPT= +! IF ("$(RANDOM)"=="$(OBJ)\isaac64.o") +BCRYPT=bcrypt.lib +! ENDIF WINPFLAG= -DTILES -DMSWIN_GRAPHICS -DWIN32CON # To store all the level files, @@ -460,7 +464,8 @@ CURSESLIB= ccommon= -c -nologo -D"_CONSOLE" -D"_CRT_NONSTDC_NO_DEPRECATE" -D"_CRT_SECURE_NO_DEPRECATE" \ -D"_LIB" -D"_SCL_SECURE_NO_DEPRECATE" -D"_VC80_UPGRADE=0x0600" -D"DLB" -D"_MBCS" \ - -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -D"NDEBUG" -D"YY_NO_UNISTD_H" $(CURSESDEF) \ + -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -D"NDEBUG" -D"YY_NO_UNISTD_H" \ + -DHAS_STDINT_H -DHAS_INLINE $(CURSESDEF) \ -EHsc -fp:precise -Gd -GF -GS -Gy \ $(CL_RECENT) -WX- -Zc:forScope -Zc:wchar_t -Zi cdebug= -analyze- -D"_DEBUG" -Gm -MTd -RTC1 -Od @@ -801,7 +806,7 @@ $(GAMEDIR)\NetHack.exe : $(O)gamedir.tag $(PDCLIB) $(O)tile.o $(O)nttty.o $(O)gu @if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR) @echo Linking $(@:\=/) $(link) $(lflagsBuild) $(conlflags) /STACK:2048 /PDB:$(GAMEDIR)\$(@B).PDB /MAP:$(O)$(@B).MAP \ - $(LIBS) $(PDCLIB) $(conlibs) -out:$@ @<<$(@B).lnk + $(LIBS) $(PDCLIB) $(conlibs) $(BCRYPT) -out:$@ @<<$(@B).lnk $(GAMEOBJ) $(TTYOBJ) $(O)nttty.o @@ -824,7 +829,7 @@ $(GAMEDIR)\NetHackW.exe : $(O)gamedir.tag $(O)tile.o $(O)ttystub.o \ @if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR) @echo Linking $(@:\=/) $(link) $(lflagsBuild) $(guilflags) /STACK:2048 /PDB:$(GAMEDIR)\$(@B).PDB \ - /MAP:$(O)$(@B).MAP $(LIBS) $(PDCLIB) $(guilibs) $(COMCTRL) -out:$@ @<<$(@B).lnk + /MAP:$(O)$(@B).MAP $(LIBS) $(PDCLIB) $(guilibs) $(COMCTRL) $(BCRYPT) -out:$@ @<<$(@B).lnk $(GAMEOBJ) $(GUIOBJ) $(O)tile.o @@ -1514,6 +1519,8 @@ $(O)tos.o: ..\sys\atari\tos.c $(HACK_H) $(INCL)\tcap.h @$(CC) $(cflagsBuild) -Fo$@ ..\sys\atari\tos.c $(O)pctty.o: ..\sys\share\pctty.c $(HACK_H) @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pctty.c +$(O)isaac64.o: ..\src\isaac64.c $(HACK_H) $(INCL)\isaac64.h $(INCL)\integer.h + @$(CC) $(cflagsBuild) -Fo$@ ..\src\isaac64.c $(O)random.o: ..\sys\share\random.c $(HACK_H) @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\random.c $(O)ioctl.o: ..\sys\share\ioctl.c $(HACK_H) $(INCL)\tcap.h diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 035ea7457..fc75071d8 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -680,6 +680,54 @@ char *name; } return; } + +#include /* Windows Crypto Next Gen (CNG) */ + +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS 0 +#endif +#ifndef STATUS_NOT_FOUND +#define STATUS_NOT_FOUND 0xC0000225 +#endif +#ifndef STATUS_UNSUCCESSFUL +#define STATUS_UNSUCCESSFUL 0xC0000001 +#endif + +unsigned long +sys_random_seed(VOID_ARGS) +{ + unsigned long ourseed = 0UL; + BCRYPT_ALG_HANDLE hRa = (BCRYPT_ALG_HANDLE) 0; + NTSTATUS status = STATUS_UNSUCCESSFUL; + boolean Plan_B = TRUE; + + status = BCryptOpenAlgorithmProvider(&hRa, BCRYPT_RNG_ALGORITHM, + (LPCWSTR) 0, 0); + if (hRa && status == STATUS_SUCCESS) { + status = BCryptGenRandom(hRa, (PUCHAR) &ourseed, + (ULONG) sizeof ourseed, 0); + if (status == STATUS_SUCCESS) { + BCryptCloseAlgorithmProvider(hRa,0); + has_strong_rngseed = TRUE; + Plan_B = FALSE; + } + } + + if (Plan_B) { + time_t datetime = 0; + const char *emsg; + + if (status == STATUS_NOT_FOUND) + emsg = "BCRYPT_RNG_ALGORITHM not avail, falling back"; + else + emsg = "Other failure than algorithm not avail"; + paniclog("sys_random_seed", emsg); /* leaves clue, doesn't exit */ + (void) time(&datetime); + ourseed = (unsigned long) datetime; + } + return ourseed; +} + #endif /* WIN32 */ /*winnt.c*/ diff --git a/win/win32/vs2017/NetHack.vcxproj b/win/win32/vs2017/NetHack.vcxproj index ee086fcc5..3a4412efe 100644 --- a/win/win32/vs2017/NetHack.vcxproj +++ b/win/win32/vs2017/NetHack.vcxproj @@ -37,7 +37,7 @@ TILES;WIN32CON;DLB;MSWIN_GRAPHICS;SAFEPROCS;_LIB;%(PreprocessorDefinitions) - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;bcrypt.lib;%(AdditionalDependencies) @@ -76,6 +76,7 @@ + @@ -151,7 +152,6 @@ - @@ -194,6 +194,7 @@ + diff --git a/win/win32/vs2017/NetHackW.vcxproj b/win/win32/vs2017/NetHackW.vcxproj index 93c2e447b..e801b1583 100644 --- a/win/win32/vs2017/NetHackW.vcxproj +++ b/win/win32/vs2017/NetHackW.vcxproj @@ -28,7 +28,7 @@ Windows - comctl32.lib;winmm.lib;%(AdditionalDependencies) + comctl32.lib;winmm.lib;bcrypt.lib;%(AdditionalDependencies) $(WinWin32Dir)NethackW.exe.manifest;%(AdditionalManifestFiles) @@ -70,6 +70,7 @@ + @@ -146,7 +147,6 @@ - TTYSTUB;