From ce5184c3da2d9a8f029745340d37d655db056021 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 28 Jan 2019 04:45:26 +0000 Subject: [PATCH 01/18] Don't advance the main RNG during hallucination This is based on the multiple-RNGs code fron NetHack4, but using only the parts relevant to the display RNG (and with substantial changes, both because of post-3.4.3 changes, and because Nethack4's display code is based on Slash'EM's rather than NetHack's). --- include/display.h | 69 ++++++++++++++++++++++++++++------------------- include/extern.h | 3 ++- src/apply.c | 13 ++++----- src/detect.c | 22 ++++++++++----- src/display.c | 31 ++++++++++++--------- src/do_name.c | 19 ++++++++----- src/dothrow.c | 6 ++--- src/engrave.c | 4 +-- src/hack.c | 4 +-- src/invent.c | 7 ++--- src/mthrowu.c | 2 +- src/muse.c | 2 +- src/pager.c | 7 ++--- src/pickup.c | 4 +-- src/pray.c | 13 ++++++--- src/rnd.c | 14 ++++++++++ src/rumors.c | 8 +++--- src/trap.c | 2 +- src/uhitm.c | 2 +- src/worm.c | 7 ++--- src/zap.c | 4 +-- 21 files changed, 150 insertions(+), 93 deletions(-) diff --git a/include/display.h b/include/display.h index 1334be2cc..abede528d 100644 --- a/include/display.h +++ b/include/display.h @@ -146,9 +146,9 @@ * * Respectively return a random monster, object, or trap number. */ -#define random_monster() rn2(NUMMONS) -#define random_object() rn1(NUM_OBJECTS - 1, 1) -#define random_trap() rn1(TRAPNUM - 1, 1) +#define random_monster(rng) rng(NUMMONS) +#define random_object(rng) (rng(NUM_OBJECTS - 1) + 1) +#define random_trap(rng) (rng(TRAPNUM - 1) + 1) /* * what_obj() @@ -156,11 +156,23 @@ * what_trap() * * If hallucinating, choose a random object/monster, otherwise, use the one - * given. + * given. Use the given rng to handle hallucination. */ -#define what_obj(obj) (Hallucination ? random_object() : obj) -#define what_mon(mon) (Hallucination ? random_monster() : mon) -#define what_trap(trp) (Hallucination ? random_trap() : trp) +#define what_obj(obj, rng) (Hallucination ? random_object(rng) : obj) +#define what_mon(mon, rng) (Hallucination ? random_monster(rng) : mon) +#define what_trap(trp, rng) (Hallucination ? random_trap(rng) : trp) + +/* + * newsym_rn2 + * + * An appropriate random number generator for use with newsym(), when + * randomness is needed there. This is currently hardcoded as + * rn2_on_display_rng, but is futureproofed for cases where we might + * want to prevent display-random objects entering the character's + * memory (this isn't important at present but may be if we need + * reproducible gameplay for some reason). + */ +#define newsym_rn2 rn2_on_display_rng /* * covers_objects() @@ -196,9 +208,10 @@ * Display the hero. It is assumed that all checks necessary to determine * _if_ the hero can be seen have already been done. */ -#define maybe_display_usteed(otherwise_self) \ - ((u.usteed && mon_visible(u.usteed)) ? ridden_mon_to_glyph(u.usteed) \ - : (otherwise_self)) +#define maybe_display_usteed(otherwise_self) \ + ((u.usteed && mon_visible(u.usteed)) \ + ? ridden_mon_to_glyph(u.usteed, rn2_on_display_rng) \ + : (otherwise_self)) #define display_self() \ show_glyph(u.ux, u.uy, \ @@ -282,27 +295,27 @@ #define GLYPH_INVISIBLE GLYPH_INVIS_OFF #define warning_to_glyph(mwarnlev) ((mwarnlev) + GLYPH_WARNING_OFF) -#define mon_to_glyph(mon) \ - ((int) what_mon(monsndx((mon)->data)) + GLYPH_MON_OFF) -#define detected_mon_to_glyph(mon) \ - ((int) what_mon(monsndx((mon)->data)) + GLYPH_DETECT_OFF) -#define ridden_mon_to_glyph(mon) \ - ((int) what_mon(monsndx((mon)->data)) + GLYPH_RIDDEN_OFF) -#define pet_to_glyph(mon) \ - ((int) what_mon(monsndx((mon)->data)) + GLYPH_PET_OFF) +#define mon_to_glyph(mon, rng) \ + ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_MON_OFF) +#define detected_mon_to_glyph(mon, rng) \ + ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_DETECT_OFF) +#define ridden_mon_to_glyph(mon, rng) \ + ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_RIDDEN_OFF) +#define pet_to_glyph(mon, rng) \ + ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_PET_OFF) /* This has the unfortunate side effect of needing a global variable */ /* to store a result. 'otg_temp' is defined and declared in decl.{ch}. */ -#define random_obj_to_glyph() \ - ((otg_temp = random_object()) == CORPSE \ - ? random_monster() + GLYPH_BODY_OFF \ +#define random_obj_to_glyph(rng) \ + ((otg_temp = random_object(rng)) == CORPSE \ + ? random_monster(rng) + GLYPH_BODY_OFF \ : otg_temp + GLYPH_OBJ_OFF) -#define obj_to_glyph(obj) \ +#define obj_to_glyph(obj, rng) \ (((obj)->otyp == STATUE) \ - ? statue_to_glyph(obj) \ + ? statue_to_glyph(obj, rng) \ : Hallucination \ - ? random_obj_to_glyph() \ + ? random_obj_to_glyph(rng) \ : ((obj)->otyp == CORPSE) \ ? (int) (obj)->corpsenm + GLYPH_BODY_OFF \ : (int) (obj)->otyp + GLYPH_OBJ_OFF) @@ -310,16 +323,16 @@ /* MRKR: Statues now have glyphs corresponding to the monster they */ /* represent and look like monsters when you are hallucinating. */ -#define statue_to_glyph(obj) \ - (Hallucination ? random_monster() + GLYPH_MON_OFF \ +#define statue_to_glyph(obj, rng) \ + (Hallucination ? random_monster(rng) + GLYPH_MON_OFF \ : (int) (obj)->corpsenm + GLYPH_STATUE_OFF) #define cmap_to_glyph(cmap_idx) ((int) (cmap_idx) + GLYPH_CMAP_OFF) #define explosion_to_glyph(expltype, idx) \ ((((expltype) * MAXEXPCHARS) + ((idx) - S_explode1)) + GLYPH_EXPLODE_OFF) -#define trap_to_glyph(trap) \ - cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp))) +#define trap_to_glyph(trap, rng) \ + cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp, rng))) /* Not affected by hallucination. Gives a generic body for CORPSE */ /* MRKR: ...and the generic statue */ diff --git a/include/extern.h b/include/extern.h index 4f63d9963..947546839 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2104,6 +2104,7 @@ E void FDECL(genl_outrip, (winid, int, time_t)); /* ### rnd.c ### */ E int FDECL(rn2, (int)); +E int FDECL(rn2_on_display_rng, (int)); E int FDECL(rnl, (int)); E int FDECL(rnd, (int)); E int FDECL(d, (int, int)); @@ -2148,7 +2149,7 @@ E const char *NDECL(Goodbye); /* ### rumors.c ### */ E char *FDECL(getrumor, (int, char *, BOOLEAN_P)); -E char *FDECL(get_rnd_text, (const char *, char *)); +E char *FDECL(get_rnd_text, (const char *, char *, int FDECL((*), (int)))); E void FDECL(outrumor, (int, int)); E void FDECL(outoracle, (BOOLEAN_P, BOOLEAN_P)); E void FDECL(save_oracles, (int, int)); diff --git a/src/apply.c b/src/apply.c index dbde93fba..fc7cc7efa 100644 --- a/src/apply.c +++ b/src/apply.c @@ -241,7 +241,7 @@ int rx, ry, *resp; int visglyph, corpseglyph; visglyph = glyph_at(rx, ry); - corpseglyph = obj_to_glyph(corpse); + corpseglyph = obj_to_glyph(corpse, rn2); if (Blind && (visglyph != corpseglyph)) map_object(corpse, TRUE); @@ -2501,7 +2501,7 @@ struct obj *otmp; ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP; if (otmp == trapinfo.tobj && u.ux == trapinfo.tx && u.uy == trapinfo.ty) { You("resume setting %s%s.", shk_your(buf, otmp), - defsyms[trap_to_defsym(what_trap(ttyp))].explanation); + defsyms[trap_to_defsym(what_trap(ttyp, rn2))].explanation); set_occupation(set_trap, occutext, 0); return; } @@ -2526,7 +2526,8 @@ struct obj *otmp; chance = (rnl(10) > 5); You("aren't very skilled at reaching from %s.", mon_nam(u.usteed)); Sprintf(buf, "Continue your attempt to set %s?", - the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation)); + the(defsyms[trap_to_defsym(what_trap(ttyp, rn2))] + .explanation)); if (yn(buf) == 'y') { if (chance) { switch (ttyp) { @@ -2537,7 +2538,7 @@ struct obj *otmp; case BEAR_TRAP: /* drop it without arming it */ reset_trapset(); You("drop %s!", - the(defsyms[trap_to_defsym(what_trap(ttyp))] + the(defsyms[trap_to_defsym(what_trap(ttyp, rn2))] .explanation)); dropx(otmp); return; @@ -2549,7 +2550,7 @@ struct obj *otmp; } } You("begin setting %s%s.", shk_your(buf, otmp), - defsyms[trap_to_defsym(what_trap(ttyp))].explanation); + defsyms[trap_to_defsym(what_trap(ttyp, rn2))].explanation); set_occupation(set_trap, occutext, 0); return; } @@ -2582,7 +2583,7 @@ set_trap() } if (!trapinfo.force_bungle) You("finish arming %s.", - the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation)); + the(defsyms[trap_to_defsym(what_trap(ttyp, rn2))].explanation)); if (((otmp->cursed || Fumbling) && (rnl(10) > 5)) || trapinfo.force_bungle) dotrap(ttmp, diff --git a/src/detect.c b/src/detect.c index e6c5778af..545f3906e 100644 --- a/src/detect.c +++ b/src/detect.c @@ -78,10 +78,12 @@ struct monst *mtmp; boolean showtail; { if (def_monsyms[(int) mtmp->data->mlet].sym == ' ') - show_glyph(mtmp->mx, mtmp->my, detected_mon_to_glyph(mtmp)); - else show_glyph(mtmp->mx, mtmp->my, - mtmp->mtame ? pet_to_glyph(mtmp) : mon_to_glyph(mtmp)); + detected_mon_to_glyph(mtmp, newsym_rn2)); + else + show_glyph(mtmp->mx, mtmp->my, mtmp->mtame + ? pet_to_glyph(mtmp, newsym_rn2) + : mon_to_glyph(mtmp, newsym_rn2)); if (showtail && mtmp->data == &mons[PM_LONG_WORM]) detect_wsegs(mtmp, 0); @@ -1591,14 +1593,20 @@ void find_trap(trap) struct trap *trap; { - int tt = what_trap(trap->ttyp); + int tt = what_trap(trap->ttyp, rn2); boolean cleared = FALSE; trap->tseen = 1; exercise(A_WIS, TRUE); feel_newsym(trap->tx, trap->ty); - if (levl[trap->tx][trap->ty].glyph != trap_to_glyph(trap)) { + /* The "Hallucination ||" is to preserve 3.6.1 behaviour, but this + behaviour might need a rework in the hallucination case + (e.g. to not prompt if any trap glyph appears on the + square). */ + if (Hallucination || + levl[trap->tx][trap->ty].glyph != + trap_to_glyph(trap, rn2_on_display_rng)) { /* There's too much clutter to see your find otherwise */ cls(); map_trap(trap, 1); @@ -1832,7 +1840,7 @@ int default_glyph, which_subset; an object, replacing any object or trap at its spot) */ glyph = !swallowed ? glyph_at(x, y) : levl_glyph; if (keep_mons && x == u.ux && y == u.uy && swallowed) - glyph = mon_to_glyph(u.ustuck); + glyph = mon_to_glyph(u.ustuck, rn2_on_display_rng); else if (((glyph_is_monster(glyph) || glyph_is_warning(glyph)) && !keep_mons) || glyph_is_swallow(glyph)) @@ -1841,7 +1849,7 @@ int default_glyph, which_subset; || glyph_is_invisible(glyph)) && keep_traps && !covers_traps(x, y)) { if ((t = t_at(x, y)) != 0 && t->tseen) - glyph = trap_to_glyph(t); + glyph = trap_to_glyph(t, rn2_on_display_rng); } if ((glyph_is_object(glyph) && !keep_objs) || (glyph_is_trap(glyph) && !keep_traps) diff --git a/src/display.c b/src/display.c index 129b63fd3..b5bdac208 100644 --- a/src/display.c +++ b/src/display.c @@ -222,7 +222,7 @@ register struct trap *trap; register int show; { register int x = trap->tx, y = trap->ty; - register int glyph = trap_to_glyph(trap); + register int glyph = trap_to_glyph(trap, newsym_rn2); if (level.flags.hero_memory) levl[x][y].glyph = glyph; @@ -242,14 +242,14 @@ register struct obj *obj; register int show; { register int x = obj->ox, y = obj->oy; - register int glyph = obj_to_glyph(obj); + register int glyph = obj_to_glyph(obj, newsym_rn2); if (level.flags.hero_memory) { /* MRKR: While hallucinating, statues are seen as random monsters */ /* but remembered as random objects. */ if (Hallucination && obj->otyp == STATUE) { - levl[x][y].glyph = random_obj_to_glyph(); + levl[x][y].glyph = random_obj_to_glyph(newsym_rn2); } else { levl[x][y].glyph = glyph; } @@ -394,7 +394,7 @@ xchar worm_tail; /* mon is actually a worm tail */ (int) mon->m_ap_type); /*FALLTHRU*/ case M_AP_NOTHING: - show_glyph(x, y, mon_to_glyph(mon)); + show_glyph(x, y, mon_to_glyph(mon, newsym_rn2)); break; case M_AP_FURNITURE: { @@ -434,7 +434,8 @@ xchar worm_tail; /* mon is actually a worm tail */ case M_AP_MONSTER: show_glyph(x, y, - monnum_to_glyph(what_mon((int) mon->mappearance))); + monnum_to_glyph(what_mon((int) mon->mappearance, + rn2_on_display_rng))); break; } } @@ -456,17 +457,19 @@ xchar worm_tail; /* mon is actually a worm tail */ if (worm_tail) num = petnum_to_glyph(PM_LONG_WORM_TAIL); else - num = pet_to_glyph(mon); + num = pet_to_glyph(mon, rn2_on_display_rng); } else if (sightflags == DETECTED) { if (worm_tail) - num = detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)); + num = detected_monnum_to_glyph( + what_mon(PM_LONG_WORM_TAIL, rn2_on_display_rng)); else - num = detected_mon_to_glyph(mon); + num = detected_mon_to_glyph(mon, rn2_on_display_rng); } else { if (worm_tail) - num = monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)); + num = monnum_to_glyph( + what_mon(PM_LONG_WORM_TAIL, rn2_on_display_rng)); else - num = mon_to_glyph(mon); + num = mon_to_glyph(mon, rn2_on_display_rng); } show_glyph(x, y, num); } @@ -489,10 +492,11 @@ register struct monst *mon; int glyph; if (mon_warning(mon)) { - int wl = Hallucination ? rn1(WARNCOUNT - 1, 1) : warning_of(mon); + int wl = Hallucination ? + rn2_on_display_rng(WARNCOUNT - 1) + 1 : warning_of(mon); glyph = warning_to_glyph(wl); } else if (MATCH_WARN_OF_MON(mon)) { - glyph = mon_to_glyph(mon); + glyph = mon_to_glyph(mon, rn2_on_display_rng); } else { impossible("display_warning did not match warning type?"); return; @@ -1751,7 +1755,8 @@ int loc; impossible("swallow_to_glyph: bad swallow location"); loc = S_sw_br; } - return ((int) (what_mon(mnum) << 3) | (loc - S_sw_tl)) + GLYPH_SWALLOW_OFF; + return ((int) (what_mon(mnum, rn2_on_display_rng) << 3) | + (loc - S_sw_tl)) + GLYPH_SWALLOW_OFF; } /* diff --git a/src/do_name.c b/src/do_name.c index 168f92b0a..753c509f1 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -1538,8 +1538,12 @@ namefloorobj() unames[0] = ((Upolyd ? u.mfemale : flags.female) && urole.name.f) ? urole.name.f : urole.name.m; - /* random rank title for hero's role */ - unames[1] = rank_of(rnd(30), Role_switch, flags.female); + /* random rank title for hero's role + + note: the 30 is hardcoded in xlev_to_rank, so should be + hardcoded here too */ + unames[1] = rank_of(rn2_on_display_rng(30) + 1, + Role_switch, flags.female); /* random fake monster */ unames[2] = bogusmon(tmpbuf, (char *) 0); /* increased chance for fake monster */ @@ -1550,7 +1554,7 @@ namefloorobj() unames[5] = "Wibbly Wobbly"; pline("%s %s to call you \"%s.\"", The(buf), use_plural ? "decide" : "decides", - unames[rn2(SIZE(unames))]); + unames[rn2_on_display_rng(SIZE(unames))]); } else if (!objtyp_is_callable(obj->otyp)) { pline("%s %s can't be assigned a type name.", use_plural ? "Those" : "That", buf); @@ -1930,7 +1934,7 @@ char *buf, *code; { char *mname = buf; - get_rnd_text(BOGUSMONFILE, buf); + get_rnd_text(BOGUSMONFILE, buf, rn2_on_display_rng); /* strip prefix if present */ if (!letter(*mname)) { if (code) @@ -1957,7 +1961,7 @@ char *code; *code = '\0'; do { - name = rn1(SPECIAL_PM + BOGUSMONSIZE - LOW_PM, LOW_PM); + name = rn2_on_display_rng(SPECIAL_PM + BOGUSMONSIZE - LOW_PM) + LOW_PM; } while (name < SPECIAL_PM && (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN))); @@ -2013,8 +2017,9 @@ const char * hcolor(colorpref) const char *colorpref; { - return (Hallucination || !colorpref) ? hcolors[rn2(SIZE(hcolors))] - : colorpref; + return (Hallucination || !colorpref) + ? hcolors[rn2_on_display_rng(SIZE(hcolors))] + : colorpref; } /* return a random real color unless hallucinating */ diff --git a/src/dothrow.c b/src/dothrow.c index de1afca9c..7541bc978 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1076,7 +1076,7 @@ struct obj *obj; if ((u.dx || u.dy) && (bhitpos.x != u.ux || bhitpos.y != u.uy)) { int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy; - tmp_at(DISP_FLASH, obj_to_glyph(obj)); + tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng)); while (isok(x,y) && (x != u.ux || y != u.uy)) { tmp_at(x, y); delay_output(); @@ -1145,7 +1145,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ bhitpos.x = mon->mx; bhitpos.y = mon->my; if (tethered_weapon) - tmp_at(DISP_TETHER, obj_to_glyph(obj)); + tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng)); } else if (u.dz) { if (u.dz < 0 /* Mjollnir must we wielded to be thrown--caller verifies this; @@ -1374,7 +1374,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ } if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && breaktest(obj)) { - tmp_at(DISP_FLASH, obj_to_glyph(obj)); + tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng)); tmp_at(bhitpos.x, bhitpos.y); delay_output(); tmp_at(DISP_END, 0); diff --git a/src/engrave.c b/src/engrave.c index 39c4005be..d127c4495 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -18,7 +18,7 @@ char *outbuf; /* a random engraving may come from the "rumors" file, or from the "engrave" file (formerly in an array here) */ if (!rn2(4) || !(rumor = getrumor(0, outbuf, TRUE)) || !*rumor) - (void) get_rnd_text(ENGRAVEFILE, outbuf); + (void) get_rnd_text(ENGRAVEFILE, outbuf, rn2); wipeout_text(outbuf, (int) (strlen(outbuf) / 4), 0); return outbuf; @@ -1294,7 +1294,7 @@ const char *str; /* Engrave the headstone */ del_engr_at(x, y); if (!str) - str = get_rnd_text(EPITAPHFILE, buf); + str = get_rnd_text(EPITAPHFILE, buf, rn2); make_engr_at(x, y, str, 0L, HEADSTONE); return; } diff --git a/src/hack.c b/src/hack.c index 25dd23a31..a42334c92 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1466,7 +1466,7 @@ domove_core() if (context.run >= 2) { if (iflags.mention_walls) { if (trap && trap->tseen) { - int tt = what_trap(trap->ttyp); + int tt = what_trap(trap->ttyp, rn2_on_display_rng); You("stop in front of %s.", an(defsyms[trap_to_defsym(tt)].explanation)); @@ -2709,7 +2709,7 @@ lookaround() goto bcorr; /* if you must */ if (x == u.ux + u.dx && y == u.uy + u.dy) { if (iflags.mention_walls) { - int tt = what_trap(trap->ttyp); + int tt = what_trap(trap->ttyp, rn2_on_display_rng); You("stop in front of %s.", an(defsyms[trap_to_defsym(tt)].explanation)); } diff --git a/src/invent.c b/src/invent.c index 0c1e45e23..01250e1af 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2691,8 +2691,8 @@ long *out_cnt; any.a_obj = otmp; else any.a_char = ilet; - add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE, - doname(otmp), MENU_UNSELECTED); + add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng), &any, ilet, + 0, ATR_NONE, doname(otmp), MENU_UNSELECTED); } } if (flags.sortpack) { @@ -2805,7 +2805,8 @@ char avoidlet; classcount++; } any.a_char = ilet; - add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE, + add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng), + &any, ilet, 0, ATR_NONE, doname(otmp), MENU_UNSELECTED); } } diff --git a/src/mthrowu.c b/src/mthrowu.c index 588a516c8..862c6cca1 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -532,7 +532,7 @@ struct obj *obj; /* missile (or stack providing it) */ * be careful not to use either one after it's been freed. */ if (sym) - tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); + tmp_at(DISP_FLASH, obj_to_glyph(singleobj, rn2_on_display_rng)); while (range-- > 0) { /* Actually the loop is always exited by break */ bhitpos.x += dx; bhitpos.y += dy; diff --git a/src/muse.c b/src/muse.c index e98bbe553..ec533c077 100644 --- a/src/muse.c +++ b/src/muse.c @@ -1976,7 +1976,7 @@ struct monst *mtmp; #ifdef CLIPPING cliparound(mtmp->mx, mtmp->my); #endif - show_glyph(mtmp->mx, mtmp->my, mon_to_glyph(mtmp)); + show_glyph(mtmp->mx, mtmp->my, mon_to_glyph(mtmp, rn2)); display_self(); You_feel("aggravated at %s.", noit_mon_nam(mtmp)); display_nhwindow(WIN_MAP, TRUE); diff --git a/src/pager.c b/src/pager.c index 693a412fa..e0c727479 100644 --- a/src/pager.c +++ b/src/pager.c @@ -381,7 +381,8 @@ char *buf, *monbuf; buf[0] = monbuf[0] = '\0'; glyph = glyph_at(x, y); if (u.ux == x && u.uy == y && canspotself() - && !(iflags.save_uswallow && glyph == mon_to_glyph(u.ustuck)) + && !(iflags.save_uswallow && + glyph == mon_to_glyph(u.ustuck, rn2_on_display_rng)) && (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)) { /* fill in buf[] */ (void) self_lookat(buf); @@ -435,7 +436,7 @@ char *buf, *monbuf; } else if (glyph_is_object(glyph)) { look_at_object(buf, x, y, glyph); /* fill in buf[] */ } else if (glyph_is_trap(glyph)) { - int tnum = what_trap(glyph_to_trap(glyph)); + int tnum = what_trap(glyph_to_trap(glyph), rn2_on_display_rng); /* Trap detection displays a bear trap at locations having * a trapped door or trapped container or both. @@ -1487,7 +1488,7 @@ doidtrap() if (u.dz < 0 ? is_hole(tt) : tt == ROCKTRAP) break; } - tt = what_trap(tt); + tt = what_trap(tt, rn2_on_display_rng); pline("That is %s%s%s.", an(defsyms[trap_to_defsym(tt)].explanation), !trap->madeby_u diff --git a/src/pickup.c b/src/pickup.c index 437357896..8842e140b 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -914,7 +914,7 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */ } any.a_obj = curr; - add_menu(win, obj_to_glyph(curr), &any, + add_menu(win, obj_to_glyph(curr, rn2_on_display_rng), &any, (qflags & USE_INVLET) ? curr->invlet : (first && curr->oclass == COIN_CLASS) ? '$' : 0, def_oc_syms[(int) objects[curr->otyp].oc_class].sym, @@ -939,7 +939,7 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */ fake_hero_object = zeroobj; fake_hero_object.quan = 1L; /* not strictly necessary... */ any.a_obj = &fake_hero_object; - add_menu(win, mon_to_glyph(&youmonst), &any, + add_menu(win, mon_to_glyph(&youmonst, rn2_on_display_rng), &any, /* fake inventory letter, no group accelerator */ CONTAINED_SYM, 0, ATR_NONE, an(self_lookat(buf)), MENU_UNSELECTED); diff --git a/src/pray.c b/src/pray.c index e1f55cb49..ff9532fbd 100644 --- a/src/pray.c +++ b/src/pray.c @@ -2095,13 +2095,18 @@ aligntyp alignment; if (!Hallucination) return align_gname(alignment); + /* Count the roles, so that we can pick one at random. */ + int rolecount = 0; + while (roles[rolecount].filecode) + rolecount++; + /* The priest may not have initialized god names. If this is the - * case, and we roll priest, we need to try again. */ + case, and we roll priest, we need to try again. */ do - which = randrole(); + which = rn2_on_display_rng(rolecount); while (!roles[which].lgod); - switch (rn2(9)) { + switch (rn2_on_display_rng(9)) { case 0: case 1: gnam = roles[which].lgod; @@ -2116,7 +2121,7 @@ aligntyp alignment; break; case 6: case 7: - gnam = hallu_gods[rn2(sizeof hallu_gods / sizeof *hallu_gods)]; + gnam = hallu_gods[rn2_on_display_rng(SIZE(hallu_gods))]; break; case 8: gnam = Moloch; diff --git a/src/rnd.c b/src/rnd.c index c3627e854..70932284a 100644 --- a/src/rnd.c +++ b/src/rnd.c @@ -34,6 +34,20 @@ register int x; #endif } +/* 0 <= rn2(x) < x, but on a different sequence from the "main" rn2; + used in cases where the answer doesn't affect gameplay and we don't + want to give users easy control over the main RNG sequence. This is + an intentionally low-quality RNG to discourage its use for anything + gameplay-affecting; please use a better RNG in that case. */ +int +rn2_on_display_rng(x) +register int x; +{ + static unsigned seed = 1; + seed *= 2739110765; + return (int)((seed >> 16) % (unsigned)x); +} + /* 0 <= rnl(x) < x; sometimes subtracting Luck; good luck approaches 0, bad luck approaches (x-1) */ int diff --git a/src/rumors.c b/src/rumors.c index 033a0126c..c8d05be32 100644 --- a/src/rumors.c +++ b/src/rumors.c @@ -280,11 +280,13 @@ rumor_check() } } -/* Gets a random line of text from file 'fname', and returns it. */ +/* Gets a random line of text from file 'fname', and returns it. + rng is the random number generator to use, and should act like rn2 does. */ char * -get_rnd_text(fname, buf) +get_rnd_text(fname, buf, rng) const char *fname; char *buf; +int FDECL((*rng), (int)); { dlb *fh; @@ -305,7 +307,7 @@ char *buf; (void) dlb_fseek(fh, 0L, SEEK_END); endtxt = dlb_ftell(fh); sizetxt = endtxt - starttxt; - tidbit = Rand() % sizetxt; + tidbit = rng(sizetxt); (void) dlb_fseek(fh, starttxt + tidbit, SEEK_SET); (void) dlb_fgets(line, sizeof line, fh); diff --git a/src/trap.c b/src/trap.c index 50f74b79c..f422241a6 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1814,7 +1814,7 @@ int style; delaycnt = 1; if (!cansee(bhitpos.x, bhitpos.y)) curs_on_u(); - tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); + tmp_at(DISP_FLASH, obj_to_glyph(singleobj, rn2_on_display_rng)); tmp_at(bhitpos.x, bhitpos.y); } /* Mark a spot to place object in bones files to prevent diff --git a/src/uhitm.c b/src/uhitm.c index cefe009eb..b3a8b10c9 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -2023,7 +2023,7 @@ struct monst *mdef; { if (!Invisible) { map_location(u.ux, u.uy, TRUE); - tmp_at(DISP_ALWAYS, mon_to_glyph(&youmonst)); + tmp_at(DISP_ALWAYS, mon_to_glyph(&youmonst, rn2_on_display_rng)); tmp_at(mdef->mx, mdef->my); } You("engulf %s!", mon_nam(mdef)); diff --git a/src/worm.c b/src/worm.c index faf257710..80d644499 100644 --- a/src/worm.c +++ b/src/worm.c @@ -457,13 +457,14 @@ boolean use_detection_glyph; struct wseg *curr = wtails[worm->wormno]; /* if (!mtmp->wormno) return; bullet proofing */ + int what_tail = what_mon(PM_LONG_WORM_TAIL, newsym_rn2); while (curr != wheads[worm->wormno]) { num = use_detection_glyph - ? detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)) + ? detected_monnum_to_glyph(what_tail) : (worm->mtame - ? petnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)) - : monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))); + ? petnum_to_glyph(what_tail) + : monnum_to_glyph(what_tail)); show_glyph(curr->wx, curr->wy, num); curr = curr->nseg; } diff --git a/src/zap.c b/src/zap.c index ba90e34c3..95c5aaa2c 100644 --- a/src/zap.c +++ b/src/zap.c @@ -3200,9 +3200,9 @@ struct obj **pobj; /* object tossed/used, set to NULL } else if (weapon == THROWN_TETHERED_WEAPON && obj) { tethered_weapon = TRUE; weapon = THROWN_WEAPON; /* simplify if's that follow below */ - tmp_at(DISP_TETHER, obj_to_glyph(obj)); + tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng)); } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) - tmp_at(DISP_FLASH, obj_to_glyph(obj)); + tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng)); while (range-- > 0) { int x, y; From 86d694c61b62750d314c01f57cdb6c3fa0ca0f5c Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Fri, 11 Jan 2019 19:08:22 +0100 Subject: [PATCH 02/18] read rng seed from random number source device Linux and BSD system have random number source devices that can be used as source for a unguessable seed source. Other platforms fall back to generate the seed with gettime(). --- include/extern.h | 3 ++- include/unixconf.h | 13 ++++++++++++ src/hacklib.c | 51 ++++++++++++++++++++++++++++++++++++---------- src/options.c | 2 +- 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/include/extern.h b/include/extern.h index 4f63d9963..d85ad5f8c 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 diff --git a/include/unixconf.h b/include/unixconf.h index 0c42c6040..3e4748ea2 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -408,5 +408,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/src/hacklib.c b/src/hacklib.c index d0c6915f0..8ceb9fcde 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -848,12 +848,23 @@ extern struct tm *FDECL(localtime, (time_t *)); #endif STATIC_DCL struct tm *NDECL(getlt); -void -setrandom() +/* Returns a number suitable as seed for the random number generator. */ +static unsigned long +get_random_seed() { - unsigned long seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ + unsigned long seed = 0; +#ifdef DEV_RANDOM + FILE *fptr = NULL; -#if defined(UNIX) || defined(VMS) + fptr = fopen(DEV_RANDOM, "r"); + if (fptr) { + fread(&seed, sizeof(long), 1, fptr); + } + fclose(fptr); +#else + seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ + +# if defined(UNIX) || defined(VMS) { unsigned long pid = (unsigned long) getpid(); @@ -864,28 +875,46 @@ setrandom() seed *= pid; } } +# endif #endif + return seed; +} +/* Sets the seed for the random number generator */ +static void +set_random(unsigned long seed) +{ /* 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 */ srandom((unsigned int) seed); #else -#if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ +# 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 +} + +/* + * Initializes the random number generator. + * Only call once. + */ +void +init_random() +{ + unsigned long seed = get_random_seed(); + set_random(seed); } time_t diff --git a/src/options.c b/src/options.c index b3fb0b79e..8fe27c8d4 100644 --- a/src/options.c +++ b/src/options.c @@ -692,7 +692,7 @@ initoptions_init() reset_commands(TRUE); /* init */ /* initialize the random number generator */ - setrandom(); + init_random(); /* for detection of configfile options specified multiple times */ iflags.opt_booldup = iflags.opt_compdup = (int *) 0; From 52d4b1a1aae176745dba871f0b01c06f081ab1ca Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Fri, 11 Jan 2019 19:23:01 +0100 Subject: [PATCH 03/18] reseed during level change to prevent deduction of rng state For platforms that read from the system's random number generator, reseed during level change, before the map of a new level is created and after level creation has finished. --- src/do.c | 1 + src/hacklib.c | 11 +++++++++++ src/mklev.c | 4 ++++ 3 files changed, 16 insertions(+) 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 8ceb9fcde..409c34007 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -917,6 +917,17 @@ init_random() set_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. */ +#ifdef DEV_RANDOM + init_random(); +#endif +} + time_t getnow() { diff --git a/src/mklev.c b/src/mklev.c index 16cc32bde..4cf5b9000 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -982,6 +982,8 @@ mklev() struct mkroom *croom; int ridx; + reseed_random(); + init_mapseen(&u.uz); if (getbones()) return; @@ -1009,6 +1011,8 @@ mklev() entered; rooms[].orig_rtype always retains original rtype value */ for (ridx = 0; ridx < SIZE(rooms); ridx++) rooms[ridx].orig_rtype = rooms[ridx].rtype; + + reseed_random(); } void From b3fde3eb412ac4785373e190c86b5e7aadff8069 Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Sun, 13 Jan 2019 15:17:59 +0100 Subject: [PATCH 04/18] fix check for stdc version in include/integer.h --- include/integer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/integer.h b/include/integer.h index 044da028d..8c9a0cbb0 100644 --- a/include/integer.h +++ b/include/integer.h @@ -7,7 +7,7 @@ #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 From c81db872fde53a9dda33a5c80be7114d79d91606 Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Sat, 12 Jan 2019 21:36:08 +0100 Subject: [PATCH 05/18] add file for the isaac64 random number generator This is the version from the Comprehensive C Archive Network, licensed under the CC0 "No Rights Reserved" Creative Common License. http://ccodearchive.net/info/isaac.html --- include/isaac64.h | 131 ++++++++++++++++++++++++ src/isaac64.c | 255 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 386 insertions(+) create mode 100644 include/isaac64.h create mode 100644 src/isaac64.c diff --git a/include/isaac64.h b/include/isaac64.h new file mode 100644 index 000000000..5c22253bd --- /dev/null +++ b/include/isaac64.h @@ -0,0 +1,131 @@ +/* CC0 (Public domain) - see LICENSE file 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< +#include +#include +#include +#include "isaac64.h" + + +#define ISAAC64_MASK ((uint64_t)0xFFFFFFFFFFFFFFFFULL) + +/* Extract ISAAC64_SZ_LOG bits (starting at bit 3). */ +static inline uint32_t lower_bits(uint64_t x) +{ + return (x & ((ISAAC64_SZ-1) << 3)) >>3; +} + +/* Extract next ISAAC64_SZ_LOG bits (starting at bit ISAAC64_SZ_LOG+2). */ +static inline uint32_t upper_bits(uint32_t y) +{ + 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)64 + ret=ldexpf((float)_bits,_base); +# if FLT_MANT_DIG>129 + while(64-nbits_needed<0){ +# else + if(64-nbits_needed<0){ +# endif + _base-=64; + nbits_needed-=64; + ret+=ldexpf((float)isaac64_next_uint64(_ctx),_base); + } + _bits=isaac64_next_uint64(_ctx)>>(64-nbits_needed); + ret+=ldexpf((float)_bits,_base-nbits_needed); +#else + if(nbits_needed>0){ + _bits=_bits<>(64-nbits_needed); + } +# if FLT_MANT_DIG<64 + else _bits>>=-nbits_needed; +# endif + ret=ldexpf((float)_bits,_base-nbits_needed); +#endif + return ret; +} + +float isaac64_next_float(isaac64_ctx *_ctx){ + return isaac64_float_bits(_ctx,0,0); +} + +float isaac64_next_signed_float(isaac64_ctx *_ctx){ + uint64_t bits; + bits=isaac64_next_uint64(_ctx); + return (1|-((int)bits&1))*isaac64_float_bits(_ctx,bits>>1,-63); +} + +/*Returns a uniform random double. + _bits: An initial set of random bits. + _base: This should be -(the number of bits in _bits), up to -64. + Return: A double uniformly distributed between 0 (inclusive) and 1 + (exclusive). + The average value was measured over 2**32 samples to be + 0.499990992392019273.*/ +static double isaac64_double_bits(isaac64_ctx *_ctx,uint64_t _bits,int _base){ + double ret; + int nbits_needed; + while(!_bits){ + if(_base+DBL_MANT_DIG64 + ret=ldexp((double)_bits,_base); +# if DBL_MANT_DIG>129 + while(64-nbits_needed<0){ +# else + if(64-nbits_needed<0){ +# endif + _base-=64; + nbits_needed-=64; + ret+=ldexp((double)isaac64_next_uint64(_ctx),_base); + } + _bits=isaac64_next_uint64(_ctx)>>(64-nbits_needed); + ret+=ldexp((double)_bits,_base-nbits_needed); +#else + if(nbits_needed>0){ + _bits=_bits<>(64-nbits_needed); + } +# if DBL_MANT_DIG<64 + else _bits>>=-nbits_needed; +# endif + ret=ldexp((double)_bits,_base-nbits_needed); +#endif + return ret; +} + +double isaac64_next_double(isaac64_ctx *_ctx){ + return isaac64_double_bits(_ctx,0,0); +} + +double isaac64_next_signed_double(isaac64_ctx *_ctx){ + uint64_t bits; + bits=isaac64_next_uint64(_ctx); + return (1|-((int)bits&1))*isaac64_double_bits(_ctx,bits>>1,-63); +} From f9433b2a87defb23c26c633105599a73e9d2a1bf Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Sun, 13 Jan 2019 16:36:55 +0100 Subject: [PATCH 06/18] integrate isaac64 into nethack Also removed the float code from isaac64 as they are not used in NetHack. --- include/config.h | 1 + include/extern.h | 3 ++ include/integer.h | 3 ++ include/isaac64.h | 46 +----------------- src/hacklib.c | 26 +++++----- src/isaac64.c | 110 +----------------------------------------- src/rnd.c | 25 ++++++++++ sys/unix/Makefile.src | 11 +++-- 8 files changed, 57 insertions(+), 168 deletions(-) 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/extern.h b/include/extern.h index d85ad5f8c..9bc4e5a24 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2104,6 +2104,9 @@ E void FDECL(genl_outrip, (winid, int, time_t)); /* ### rnd.c ### */ +#ifdef USE_ISAAC64 +E void FDECL(init_isaac64, (unsigned long)); +#endif E int FDECL(rn2, (int)); E int FDECL(rnl, (int)); E int FDECL(rnd, (int)); diff --git a/include/integer.h b/include/integer.h index 8c9a0cbb0..d340e4177 100644 --- a/include/integer.h +++ b/include/integer.h @@ -36,6 +36,9 @@ typedef int int32; typedef unsigned int uint32; #endif +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; + #endif /* !C99 */ #endif /* INTEGER_H */ diff --git a/include/isaac64.h b/include/isaac64.h index 5c22253bd..6c9b45b52 100644 --- a/include/isaac64.h +++ b/include/isaac64.h @@ -1,7 +1,7 @@ -/* CC0 (Public domain) - see LICENSE file for details */ +/* CC0 (Public domain) - see http://creativecommons.org/publicdomain/zero/1.0/ for details */ #if !defined(_isaac64_H) # define _isaac64_H (1) -# include +# include @@ -85,47 +85,5 @@ uint64_t isaac64_next_uint(isaac64_ctx *_ctx,uint64_t _n); * To generate cheaper float values that do not have these properties, use * ldexpf((float)isaac64_next_uint64(_ctx),-64); */ -float isaac64_next_float(isaac64_ctx *_ctx); -/** - * isaac64_next_signed_float - Uniform random float in the range (-1,1). - * @_ctx: The ISAAC64 instance to generate the value with. - * Returns a high-quality float uniformly distributed between -1 and 1 - * (exclusive). - * All of the float's mantissa bits are random, e.g., the least significant bit - * may still be non-zero even if the magnitude is less than 0.5, and any - * representable float in the range (-1,1) has a chance to be returned, though - * values very close to zero become increasingly unlikely. - * To generate cheaper float values that do not have these properties, use - * ldexpf((float)isaac64_next_uint64(_ctx),-63)-1; - * though this returns values in the range [-1,1). - */ -float isaac64_next_signed_float(isaac64_ctx *_ctx); -/** - * isaac64_next_double - Uniform random double in the range [0,1). - * @_ctx: The ISAAC64 instance to generate the value with. - * Returns a high-quality double uniformly distributed between 0 (inclusive) - * and 1 (exclusive). - * All of the double's mantissa bits are random, e.g., the least significant - * bit may still be non-zero even if the value is less than 0.5, and any - * representable double in the range [0,1) has a chance to be returned, though - * values very close to zero become increasingly unlikely. - * To generate cheaper double values that do not have these properties, use - * ldexp((double)isaac64_next_uint64(_ctx),-64); - */ -double isaac64_next_double(isaac64_ctx *_ctx); -/** - * isaac64_next_signed_double - Uniform random double in the range (-1,1). - * @_ctx: The ISAAC64 instance to generate the value with. - * Returns a high-quality double uniformly distributed between -1 and 1 - * (exclusive). - * All of the double's mantissa bits are random, e.g., the least significant - * bit may still be non-zero even if the value is less than 0.5, and any - * representable double in the range (-1,1) has a chance to be returned, - * though values very close to zero become increasingly unlikely. - * To generate cheaper double values that do not have these properties, use - * ldexp((double)isaac64_next_uint64(_ctx),-63)-1; - * though this returns values in the range [-1,1). - */ -double isaac64_next_signed_double(isaac64_ctx *_ctx); #endif diff --git a/src/hacklib.c b/src/hacklib.c index 409c34007..74a326efd 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -884,26 +884,30 @@ get_random_seed() static void set_random(unsigned long seed) { +#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) \ - || defined(CYGWIN32) /* system srandom() */ -# if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) - (void) -# endif - srandom((int) seed); # else -# ifdef UNIX /* system srand48() */ +# if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ + || defined(CYGWIN32) /* system srandom() */ +# if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) + (void) +# endif + srandom((int) seed); +# 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 } /* diff --git a/src/isaac64.c b/src/isaac64.c index 3a392fc9b..6a0037228 100644 --- a/src/isaac64.c +++ b/src/isaac64.c @@ -1,13 +1,10 @@ /*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 - CC0 (Public domain) - see LICENSE file for details + 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 -#include #include "isaac64.h" - #define ISAAC64_MASK ((uint64_t)0xFFFFFFFFFFFFFFFFULL) /* Extract ISAAC64_SZ_LOG bits (starting at bit 3). */ @@ -17,7 +14,7 @@ static inline uint32_t lower_bits(uint64_t x) } /* Extract next ISAAC64_SZ_LOG bits (starting at bit ISAAC64_SZ_LOG+2). */ -static inline uint32_t upper_bits(uint32_t y) +static inline uint32_t upper_bits(uint64_t y) { return (y >> (ISAAC64_SZ_LOG+3)) & (ISAAC64_SZ-1); } @@ -150,106 +147,3 @@ uint64_t isaac64_next_uint(isaac64_ctx *_ctx,uint64_t _n){ while(((d+_n-1)&ISAAC64_MASK)64 - ret=ldexpf((float)_bits,_base); -# if FLT_MANT_DIG>129 - while(64-nbits_needed<0){ -# else - if(64-nbits_needed<0){ -# endif - _base-=64; - nbits_needed-=64; - ret+=ldexpf((float)isaac64_next_uint64(_ctx),_base); - } - _bits=isaac64_next_uint64(_ctx)>>(64-nbits_needed); - ret+=ldexpf((float)_bits,_base-nbits_needed); -#else - if(nbits_needed>0){ - _bits=_bits<>(64-nbits_needed); - } -# if FLT_MANT_DIG<64 - else _bits>>=-nbits_needed; -# endif - ret=ldexpf((float)_bits,_base-nbits_needed); -#endif - return ret; -} - -float isaac64_next_float(isaac64_ctx *_ctx){ - return isaac64_float_bits(_ctx,0,0); -} - -float isaac64_next_signed_float(isaac64_ctx *_ctx){ - uint64_t bits; - bits=isaac64_next_uint64(_ctx); - return (1|-((int)bits&1))*isaac64_float_bits(_ctx,bits>>1,-63); -} - -/*Returns a uniform random double. - _bits: An initial set of random bits. - _base: This should be -(the number of bits in _bits), up to -64. - Return: A double uniformly distributed between 0 (inclusive) and 1 - (exclusive). - The average value was measured over 2**32 samples to be - 0.499990992392019273.*/ -static double isaac64_double_bits(isaac64_ctx *_ctx,uint64_t _bits,int _base){ - double ret; - int nbits_needed; - while(!_bits){ - if(_base+DBL_MANT_DIG64 - ret=ldexp((double)_bits,_base); -# if DBL_MANT_DIG>129 - while(64-nbits_needed<0){ -# else - if(64-nbits_needed<0){ -# endif - _base-=64; - nbits_needed-=64; - ret+=ldexp((double)isaac64_next_uint64(_ctx),_base); - } - _bits=isaac64_next_uint64(_ctx)>>(64-nbits_needed); - ret+=ldexp((double)_bits,_base-nbits_needed); -#else - if(nbits_needed>0){ - _bits=_bits<>(64-nbits_needed); - } -# if DBL_MANT_DIG<64 - else _bits>>=-nbits_needed; -# endif - ret=ldexp((double)_bits,_base-nbits_needed); -#endif - return ret; -} - -double isaac64_next_double(isaac64_ctx *_ctx){ - return isaac64_double_bits(_ctx,0,0); -} - -double isaac64_next_signed_double(isaac64_ctx *_ctx){ - uint64_t bits; - bits=isaac64_next_uint64(_ctx); - return (1|-((int)bits&1))*isaac64_double_bits(_ctx,bits>>1,-63); -} diff --git a/src/rnd.c b/src/rnd.c index c3627e854..9745d9ef2 100644 --- a/src/rnd.c +++ b/src/rnd.c @@ -4,6 +4,30 @@ #include "hack.h" +#ifdef USE_ISAAC64 +#include "isaac64.h" + +static isaac64_ctx rng_state; + +void +init_isaac64(unsigned long seed) +{ + unsigned char new_rng_state[sizeof(seed)]; + int i; + for (i=0; i>= 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 +40,7 @@ extern int NDECL(rand); #define RND(x) ((int) ((Rand() >> 3) % (x))) #endif #endif /* LINT */ +#endif /* 0 <= rn2(x) < x */ int 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 From 6c114640f5cb86685ee7fdec9b202294bca5dc41 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 13 Jan 2019 20:54:11 -0500 Subject: [PATCH 07/18] some system-specific adjustments for RNG routines move some system-specific seed-related stuff from hacklib.c to a system-specific source file and #define SYS_RANDOM_SEED to utilize it during build. Windows changes for random seed generation using crypto next gen (CNG) api routines. Corresponding vms changes due to disentangling of VMS and unix when the unix seed bits got moved (untested). --- include/extern.h | 1 + include/integer.h | 59 ++++++++++++++++++++++++------------------ include/ntconf.h | 12 +++++---- include/unixconf.h | 1 + include/vmsconf.h | 1 + src/hacklib.c | 32 +++++++---------------- src/rnd.c | 1 + sys/unix/unixmain.c | 27 +++++++++++++++++++ sys/vms/vmsmain.c | 18 +++++++++++++ sys/winnt/Makefile.msc | 18 ++++++++----- sys/winnt/winnt.c | 49 +++++++++++++++++++++++++++++++++++ 11 files changed, 161 insertions(+), 58 deletions(-) diff --git a/include/extern.h b/include/extern.h index 9bc4e5a24..24df9cd6a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2106,6 +2106,7 @@ E void FDECL(genl_outrip, (winid, int, time_t)); #ifdef USE_ISAAC64 E void FDECL(init_isaac64, (unsigned long)); +E long NDECL(nhrand); #endif E int FDECL(rn2, (int)); E int FDECL(rnl, (int)); diff --git a/include/integer.h b/include/integer.h index d340e4177..9f16a592d 100644 --- a/include/integer.h +++ b/include/integer.h @@ -8,37 +8,46 @@ #define INTEGER_H #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 - -typedef unsigned long uint32_t; -typedef unsigned long long uint64_t; - -#endif /* !C99 */ +typedef int64_t int64; +typedef uint64_t uint64; #endif /* INTEGER_H */ diff --git a/include/ntconf.h b/include/ntconf.h index 6859d52b0..b681680d2 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -7,7 +7,9 @@ /* #define SHELL */ /* nt use of pcsys routines caused a hang */ -#define RANDOM /* have Berkeley random(3) */ +/* #define RANDOM */ /* have Berkeley random(3) */ +#define USE_ISAAC64 + #define TEXTCOLOR /* Color text */ #define EXEPATH /* Allow .exe location to be used as HACKDIR */ @@ -25,8 +27,7 @@ game */ #define SYSCF /* Use a global configuration */ -#define SYSCF_FILE "sysconf" /* Use a file to hold the SYSCF configuration \ - */ +#define SYSCF_FILE "sysconf" /* Use a file to hold the SYSCF configuration */ #define DUMPLOG /* Enable dumplog files */ /*#define DUMPLOG_FILE "nethack-%n-%d.log"*/ @@ -35,9 +36,9 @@ #define USER_SOUNDS /*#define CHANGE_COLOR*/ /* allow palette changes */ -#define SELECTSAVED /* Provide menu of saved games to choose from at start \ - */ +#define SELECTSAVED /* Provide menu of saved games to choose from at start */ +#define SYS_RANDOM_SEED /* Use random seed derived from CNG */ /* * ----------------------------------------------------------------- * The remaining code shouldn't need modification. @@ -131,6 +132,7 @@ extern void FDECL(interject, (int)); /* suppress a warning in cppregex.cpp */ #pragma warning(disable : 4101) /* unreferenced local variable */ #endif +#define HAS_STDINT_H /* force include of stdint.h in integer.h */ #endif /* _MSC_VER */ /* The following is needed for prototypes of certain functions */ diff --git a/include/unixconf.h b/include/unixconf.h index 3e4748ea2..e4c23cd8d 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -420,6 +420,7 @@ # define DEV_RANDOM "/dev/random" # endif #endif +#define SYS_RANDOM_SEED #endif /* UNIXCONF_H */ #endif /* UNIX */ diff --git a/include/vmsconf.h b/include/vmsconf.h index 7674e8558..dfee1cb42 100644 --- a/include/vmsconf.h +++ b/include/vmsconf.h @@ -255,6 +255,7 @@ typedef __mode_t mode_t; #else #define Rand() rand() #endif +#define SYS_RANDOM_SEED #ifndef __GNUC__ #ifndef bcopy diff --git a/src/hacklib.c b/src/hacklib.c index 74a326efd..f70a4440f 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,34 +850,20 @@ extern struct tm *FDECL(localtime, (time_t *)); #endif STATIC_DCL struct tm *NDECL(getlt); +#ifdef SYS_RANDOM_SEED +extern unsigned long NDECL(sys_random_seed); +#endif + /* Returns a number suitable as seed for the random number generator. */ static unsigned long get_random_seed() { unsigned long seed = 0; -#ifdef DEV_RANDOM - FILE *fptr = NULL; - - fptr = fopen(DEV_RANDOM, "r"); - if (fptr) { - fread(&seed, sizeof(long), 1, fptr); - } - fclose(fptr); +#ifdef SYS_RANDOM_SEED + /* Platform-specific seed if one is provided */ + seed = sys_random_seed(); #else 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 #endif return seed; } @@ -927,7 +915,7 @@ reseed_random() { /* only reseed if we are certain that the seed generation is unguessable * by the players. */ -#ifdef DEV_RANDOM +#if defined(SYS_RANDOM_SEED) init_random(); #endif } diff --git a/src/rnd.c b/src/rnd.c index 9745d9ef2..67f2e4012 100644 --- a/src/rnd.c +++ b/src/rnd.c @@ -27,6 +27,7 @@ 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... */ diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index f798fa163..ac6d3c290 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -765,4 +765,31 @@ error: } #endif +#ifdef SYS_RANDOM_SEED +unsigned long +sys_random_seed() +{ + unsigned long seed; + unsigned long pid = (unsigned long) getpid(); +#ifdef DEV_RANDOM + FILE *fptr = NULL; + + fptr = fopen(DEV_RANDOM, "r"); + if (fptr) { + fread(&seed, sizeof(long), 1, fptr); + } + fclose(fptr); +#else + 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; + } +#endif + return seed; +} +#endif /* SYS_RANDOM_SEED */ + /*unixmain.c*/ diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index 75f321cb0..b3be6e4d1 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -465,4 +465,22 @@ wd_message() You("are in non-scoring explore/discovery mode."); } +#ifdef SYS_RANDOM_SEED +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; +} +#endif + /*vmsmain.c*/ diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 6dcd10d4d..e41dcac05 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -73,8 +73,8 @@ DEBUGINFO = Y # PDCurses header (.h) files and PDCURSES_C to the location # of your PDCurses C files. # -#ADD_CURSES=Y -#PDCURSES_TOP=..\..\pdcurses +ADD_CURSES=Y +PDCURSES_TOP=..\..\pdcurses # #============================================================================== # This marks the end of the BUILD DECISIONS section. @@ -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, @@ -801,7 +805,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 +828,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 +1518,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..b1f5b2b4d 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -680,6 +680,55 @@ char *name; } return; } + +#ifdef SYS_RANDOM_SEED +#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 + +#include /* Windows Crypto Next Gen (CNG) */ + +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); + 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 /* SYS_RANDOM_SEED */ + #endif /* WIN32 */ /*winnt.c*/ From 3f609bf9adbab1d127c4b75110322d4a02de3db3 Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 14 Jan 2019 20:36:50 -0500 Subject: [PATCH 08/18] define Rand() in isaac4 config Rand() was typically defined to random() or to rand(). gcc seems to provide a random() to link to on linux when sys/share/random.c is linked in, but other platforms such as Windows got an undefined refence to random() when RANDOM wasn't defined. The only direct use seems to be in get_rnd_txt() these days, in rumors.c Under the USE_ISAAC64 config, neither srandom() nor srand() are being invoked to seed those routines, and it really should be using isaac64 when USE_ISAAC64 is defined anyway. --- include/ntconf.h | 14 +++++++++----- include/os2conf.h | 5 ++++- include/pcconf.h | 6 +++++- include/unixconf.h | 5 +++++ include/vmsconf.h | 4 ++++ include/wceconf.h | 7 ++++++- 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/include/ntconf.h b/include/ntconf.h index b681680d2..f7e8ca9cd 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -7,9 +7,6 @@ /* #define SHELL */ /* nt use of pcsys routines caused a hang */ -/* #define RANDOM */ /* have Berkeley random(3) */ -#define USE_ISAAC64 - #define TEXTCOLOR /* Color text */ #define EXEPATH /* Allow .exe location to be used as HACKDIR */ @@ -37,8 +34,9 @@ /*#define CHANGE_COLOR*/ /* allow palette changes */ #define SELECTSAVED /* Provide menu of saved games to choose from at start */ - + #define SYS_RANDOM_SEED /* Use random seed derived from CNG */ + /* * ----------------------------------------------------------------- * The remaining code shouldn't need modification. @@ -182,12 +180,18 @@ extern void FDECL(interject, (int)); #include #define USE_STDARG -#ifdef RANDOM + /* Use the high quality random number routines. */ +#ifdef USE_ISAAC64 +#define Rand() rn2(RAND_MAX) +#else +#define RANDOM +#ifdef RANDOM #define Rand() random() #else #define Rand() rand() #endif +#endif #include #define FCMASK (_S_IREAD | _S_IWRITE) /* file creation mask */ diff --git a/include/os2conf.h b/include/os2conf.h index f033ef584..cde929982 100644 --- a/include/os2conf.h +++ b/include/os2conf.h @@ -78,12 +78,15 @@ #include /* the high quality random number routines */ - +#ifdef USE_ISAAC64 +#define Rand() rn2(RAND_MAX) +#else #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..9b4928831 100644 --- a/include/pcconf.h +++ b/include/pcconf.h @@ -236,12 +236,16 @@ #include #endif +/* the high quality random number routines */ +#ifdef USE_ISAAC64 +#define Rand() rn2(RAND_MAX) +#else #ifdef RANDOM -/* Use the high quality random number routines. */ #define Rand() random() #else #define Rand() rand() #endif +#endif #ifndef TOS #define FCMASK 0660 /* file creation mask */ diff --git a/include/unixconf.h b/include/unixconf.h index e4c23cd8d..c494d5307 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -347,12 +347,17 @@ #endif /* Use the high quality random number routines. */ +/* the high quality random number routines */ +#ifdef USE_ISAAC64 +#define Rand() rn2(RAND_MAX) +#else #if defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) \ || defined(RANDOM) || defined(__APPLE__) #define Rand() random() #else #define Rand() lrand48() #endif +#endif #ifdef TIMED_DELAY #if defined(SUNOS4) || defined(LINUX) || (defined(BSD) && !defined(ULTRIX)) diff --git a/include/vmsconf.h b/include/vmsconf.h index dfee1cb42..1c6ea27f9 100644 --- a/include/vmsconf.h +++ b/include/vmsconf.h @@ -243,6 +243,9 @@ typedef __mode_t mode_t; #define rindex strrchr /* Use the high quality random number routines. */ +#ifdef USE_ISAAC64 +#define Rand() rn2(RAND_MAX) +#else #if defined(RANDOM) #define Rand() random() /* VMS V7 adds these entry points to DECC$SHR; stick with the nethack-supplied @@ -255,6 +258,7 @@ typedef __mode_t mode_t; #else #define Rand() rand() #endif +#endif #define SYS_RANDOM_SEED #ifndef __GNUC__ diff --git a/include/wceconf.h b/include/wceconf.h index 7ab03f672..bc6492ab9 100644 --- a/include/wceconf.h +++ b/include/wceconf.h @@ -141,12 +141,17 @@ #define index strchr #define rindex strrchr #define USE_STDARG -#ifdef RANDOM + /* Use the high quality random number routines. */ +#ifdef USE_ISAAC64 +#define Rand() rn2(RAND_MAX) +#else +#ifdef RANDOM #define Rand() random() #else #define Rand() rand() #endif +#endif #define FCMASK 0660 /* file creation mask */ #define regularize nt_regularize From 97b8d0a50b7f27f1d31740f52c214e1a6f226b0b Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Thu, 17 Jan 2019 11:48:58 +0100 Subject: [PATCH 09/18] Don't define Rand() if isaac64 is used --- include/ntconf.h | 16 +++++++--------- include/os2conf.h | 14 ++++++-------- include/pcconf.h | 14 ++++++-------- include/unixconf.h | 14 ++++++-------- include/vmsconf.h | 22 ++++++++++------------ include/wceconf.h | 14 ++++++-------- src/rumors.c | 6 +++--- 7 files changed, 44 insertions(+), 56 deletions(-) diff --git a/include/ntconf.h b/include/ntconf.h index f7e8ca9cd..4edc63c76 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -182,15 +182,13 @@ extern void FDECL(interject, (int)); #define USE_STDARG /* Use the high quality random number routines. */ -#ifdef USE_ISAAC64 -#define Rand() rn2(RAND_MAX) -#else -#define RANDOM -#ifdef RANDOM -#define Rand() random() -#else -#define Rand() rand() -#endif +#ifndef USE_ISAAC64 +# define RANDOM +# ifdef RANDOM +# define Rand() random() +# else +# define Rand() rand() +# endif #endif #include diff --git a/include/os2conf.h b/include/os2conf.h index cde929982..fd625512a 100644 --- a/include/os2conf.h +++ b/include/os2conf.h @@ -78,14 +78,12 @@ #include /* the high quality random number routines */ -#ifdef USE_ISAAC64 -#define Rand() rn2(RAND_MAX) -#else -#ifdef RANDOM -#define Rand() random() -#else -#define Rand() rand() -#endif +#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 9b4928831..fb210b8ca 100644 --- a/include/pcconf.h +++ b/include/pcconf.h @@ -237,14 +237,12 @@ #endif /* the high quality random number routines */ -#ifdef USE_ISAAC64 -#define Rand() rn2(RAND_MAX) -#else -#ifdef RANDOM -#define Rand() random() -#else -#define Rand() rand() -#endif +#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 c494d5307..c0c80ccda 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -348,15 +348,13 @@ /* Use the high quality random number routines. */ /* the high quality random number routines */ -#ifdef USE_ISAAC64 -#define Rand() rn2(RAND_MAX) -#else -#if defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) \ +#ifndef USE_ISAAC64 +# if defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) \ || defined(RANDOM) || defined(__APPLE__) -#define Rand() random() -#else -#define Rand() lrand48() -#endif +# define Rand() random() +# else +# define Rand() lrand48() +# endif #endif #ifdef TIMED_DELAY diff --git a/include/vmsconf.h b/include/vmsconf.h index 1c6ea27f9..95749bbd6 100644 --- a/include/vmsconf.h +++ b/include/vmsconf.h @@ -243,21 +243,19 @@ typedef __mode_t mode_t; #define rindex strrchr /* Use the high quality random number routines. */ -#ifdef USE_ISAAC64 -#define Rand() rn2(RAND_MAX) -#else -#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() -#endif +# define random nh_random +# define srandom nh_srandom +# define initstate nh_initstate +# define setstate nh_setstate +# else +# define Rand() rand() +# endif #endif #define SYS_RANDOM_SEED diff --git a/include/wceconf.h b/include/wceconf.h index bc6492ab9..dcc7b6f95 100644 --- a/include/wceconf.h +++ b/include/wceconf.h @@ -143,14 +143,12 @@ #define USE_STDARG /* Use the high quality random number routines. */ -#ifdef USE_ISAAC64 -#define Rand() rn2(RAND_MAX) -#else -#ifdef RANDOM -#define Rand() random() -#else -#define Rand() rand() -#endif +#ifndef USE_ISAAC64 +# ifdef RANDOM +# define Rand() random() +# else +# define Rand() rand() +# endif #endif #define FCMASK 0660 /* file creation mask */ diff --git a/src/rumors.c b/src/rumors.c index 033a0126c..5215c105f 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"); @@ -305,7 +305,7 @@ char *buf; (void) dlb_fseek(fh, 0L, SEEK_END); endtxt = dlb_ftell(fh); sizetxt = endtxt - starttxt; - tidbit = Rand() % sizetxt; + tidbit = rn2(sizetxt); (void) dlb_fseek(fh, starttxt + tidbit, SEEK_SET); (void) dlb_fgets(line, sizeof line, fh); From 0a430cab11e2460e14fc32e6c2fc0bae5f7923cf Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 17 Jan 2019 18:30:56 -0500 Subject: [PATCH 10/18] every platform provides sys_random_seed() and SYS_RANDOM_SEED goes away --- include/ntconf.h | 2 -- include/unixconf.h | 1 - include/vmsconf.h | 1 - src/hacklib.c | 31 +++++++------------------------ sys/msdos/msdos.c | 11 +++++++++++ sys/unix/unixmain.c | 2 -- sys/vms/vmsmain.c | 2 -- sys/winnt/Makefile.msc | 4 ++-- sys/winnt/winnt.c | 6 ++---- win/win32/vs2017/NetHack.vcxproj | 5 +++-- win/win32/vs2017/NetHackW.vcxproj | 4 ++-- 11 files changed, 27 insertions(+), 42 deletions(-) diff --git a/include/ntconf.h b/include/ntconf.h index 4edc63c76..62c68cc47 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -35,8 +35,6 @@ /*#define CHANGE_COLOR*/ /* allow palette changes */ #define SELECTSAVED /* Provide menu of saved games to choose from at start */ -#define SYS_RANDOM_SEED /* Use random seed derived from CNG */ - /* * ----------------------------------------------------------------- * The remaining code shouldn't need modification. diff --git a/include/unixconf.h b/include/unixconf.h index c0c80ccda..781e3563e 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -423,7 +423,6 @@ # define DEV_RANDOM "/dev/random" # endif #endif -#define SYS_RANDOM_SEED #endif /* UNIXCONF_H */ #endif /* UNIX */ diff --git a/include/vmsconf.h b/include/vmsconf.h index 95749bbd6..40cde73a0 100644 --- a/include/vmsconf.h +++ b/include/vmsconf.h @@ -257,7 +257,6 @@ typedef __mode_t mode_t; # define Rand() rand() # endif #endif -#define SYS_RANDOM_SEED #ifndef __GNUC__ #ifndef bcopy diff --git a/src/hacklib.c b/src/hacklib.c index f70a4440f..56e301ed2 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -850,24 +850,6 @@ extern struct tm *FDECL(localtime, (time_t *)); #endif STATIC_DCL struct tm *NDECL(getlt); -#ifdef SYS_RANDOM_SEED -extern unsigned long NDECL(sys_random_seed); -#endif - -/* Returns a number suitable as seed for the random number generator. */ -static unsigned long -get_random_seed() -{ - unsigned long seed = 0; -#ifdef SYS_RANDOM_SEED - /* Platform-specific seed if one is provided */ - seed = sys_random_seed(); -#else - seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ -#endif - return seed; -} - /* Sets the seed for the random number generator */ static void set_random(unsigned long seed) @@ -898,6 +880,11 @@ set_random(unsigned long seed) #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. @@ -905,19 +892,15 @@ set_random(unsigned long seed) void init_random() { - unsigned long seed = get_random_seed(); - set_random(seed); + 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 defined(SYS_RANDOM_SEED) + /* reseed */ init_random(); -#endif } time_t 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/unixmain.c b/sys/unix/unixmain.c index ac6d3c290..6b3cf5aea 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -765,7 +765,6 @@ error: } #endif -#ifdef SYS_RANDOM_SEED unsigned long sys_random_seed() { @@ -790,6 +789,5 @@ sys_random_seed() #endif return seed; } -#endif /* SYS_RANDOM_SEED */ /*unixmain.c*/ diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index b3be6e4d1..98f04be23 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -465,7 +465,6 @@ wd_message() You("are in non-scoring explore/discovery mode."); } -#ifdef SYS_RANDOM_SEED unsigned long sys_random_seed() { @@ -481,6 +480,5 @@ sys_random_seed() } return seed; } -#endif /*vmsmain.c*/ diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index e41dcac05..ef7b6258e 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -73,8 +73,8 @@ DEBUGINFO = Y # PDCurses header (.h) files and PDCURSES_C to the location # of your PDCurses C files. # -ADD_CURSES=Y -PDCURSES_TOP=..\..\pdcurses +#ADD_CURSES=Y +#PDCURSES_TOP=..\..\pdcurses # #============================================================================== # This marks the end of the BUILD DECISIONS section. diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index b1f5b2b4d..1a1fa710e 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -681,7 +681,8 @@ char *name; return; } -#ifdef SYS_RANDOM_SEED +#include /* Windows Crypto Next Gen (CNG) */ + #ifndef STATUS_SUCCESS #define STATUS_SUCCESS 0 #endif @@ -692,8 +693,6 @@ char *name; #define STATUS_UNSUCCESSFUL 0xC0000001 #endif -#include /* Windows Crypto Next Gen (CNG) */ - unsigned long sys_random_seed(VOID_ARGS) { @@ -727,7 +726,6 @@ sys_random_seed(VOID_ARGS) } return ourseed; } -#endif /* SYS_RANDOM_SEED */ #endif /* WIN32 */ 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; From 0aa4d62a2c2944ca6b37a50034c7d6c5d662cb23 Mon Sep 17 00:00:00 2001 From: nhmall Date: Fri, 18 Jan 2019 18:42:42 -0500 Subject: [PATCH 11/18] detect rng seed strength at runtime based on algorithm not compile time based on platform features --- include/decl.h | 1 + src/decl.c | 1 + src/hacklib.c | 6 ++++-- sys/unix/unixmain.c | 1 + sys/winnt/winnt.c | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) 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/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/hacklib.c b/src/hacklib.c index 56e301ed2..60f492b37 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -899,8 +899,10 @@ init_random() void reseed_random() { - /* reseed */ - init_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/sys/unix/unixmain.c b/sys/unix/unixmain.c index 6b3cf5aea..0a1f469a7 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -776,6 +776,7 @@ sys_random_seed() fptr = fopen(DEV_RANDOM, "r"); if (fptr) { fread(&seed, sizeof(long), 1, fptr); + has_strong_rngseed = TRUE; } fclose(fptr); #else diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 1a1fa710e..fc75071d8 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -708,6 +708,7 @@ sys_random_seed(VOID_ARGS) (ULONG) sizeof ourseed, 0); if (status == STATUS_SUCCESS) { BCryptCloseAlgorithmProvider(hRa,0); + has_strong_rngseed = TRUE; Plan_B = FALSE; } } From c1327142b544ca4376a16c979ff1a3e8fa38df0c Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 26 Jan 2019 11:26:02 -0500 Subject: [PATCH 12/18] detect DEV_RANDOM fopen failure and fall back, noting it in paniclog --- sys/unix/unixmain.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 0a1f469a7..1d6500b68 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -770,24 +770,30 @@ 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; - } - fclose(fptr); -#else - 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; + 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; } From 22f8d864e2293964ed60e7a9b6b46a3a5fc430e9 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 27 Jan 2019 09:34:18 -0500 Subject: [PATCH 13/18] ntconf.h ensure Rand is always something order of preference: USE_ISAAC64 RANDOM C routine --- include/ntconf.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/include/ntconf.h b/include/ntconf.h index 62c68cc47..af41154c0 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -180,13 +180,16 @@ extern void FDECL(interject, (int)); #define USE_STDARG /* Use the high quality random number routines. */ -#ifndef USE_ISAAC64 -# define RANDOM -# ifdef RANDOM -# define Rand() random() -# else -# define Rand() rand() -# endif +#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 #include From bd730dbcaa011fabcf4f297a36f997139b89f798 Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Mon, 28 Jan 2019 15:00:04 +0100 Subject: [PATCH 14/18] workaround for C89 not supporting inline --- src/isaac64.c | 12 ++++++++++++ sys/unix/hints/macosx10.10 | 2 +- sys/unix/hints/macosx10.14 | 2 +- sys/unix/hints/macosx10.5 | 2 +- sys/unix/hints/macosx10.7 | 2 +- sys/unix/hints/macosx10.8 | 2 +- 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/isaac64.c b/src/isaac64.c index 6a0037228..6928ff72b 100644 --- a/src/isaac64.c +++ b/src/isaac64.c @@ -7,14 +7,26 @@ #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); } 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 From f53d02f0bb139e0fee5a7fcdfd9da81fc4f9169b Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 28 Jan 2019 09:44:35 -0500 Subject: [PATCH 15/18] Windows build bit --- include/ntconf.h | 2 ++ sys/winnt/Makefile.msc | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/ntconf.h b/include/ntconf.h index af41154c0..094c50c73 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -128,7 +128,9 @@ extern void FDECL(interject, (int)); /* suppress a warning in cppregex.cpp */ #pragma warning(disable : 4101) /* unreferenced local variable */ #endif +#ifndef HAS_STDINT_H #define HAS_STDINT_H /* force include of stdint.h in integer.h */ +#endif #endif /* _MSC_VER */ /* The following is needed for prototypes of certain functions */ diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index ef7b6258e..97001da6e 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -464,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 From 457e4b68aac9c9cab9e7b750fc57aa028190c0e7 Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 28 Jan 2019 19:43:55 -0500 Subject: [PATCH 16/18] merge Alex's dual rng proposal with the isaac64 rng code and adjust This is branched from Alex's hallu-rng-stability branch, with two build corrections (detect.c, zap.c), and merged with the isaac64 branch that we have ready to go. Alex's dual rng is supported by setting up the array of multiple isaac64 contexts. I stuck with Alex's approach of passing the rng function name around as the parameter (rng or rn2_on_display_rng) for the new additional parameter needed for set_random(), init_random(), reseed_random(), and init_isaac64(). --- include/extern.h | 6 +++--- src/detect.c | 4 ++-- src/do.c | 3 ++- src/hacklib.c | 34 ++++++++++++++++++++++------------ src/mklev.c | 6 ++++-- src/options.c | 5 +++-- src/zap.c | 2 +- 7 files changed, 37 insertions(+), 23 deletions(-) diff --git a/include/extern.h b/include/extern.h index 7e48246f5..f67d09c85 100644 --- a/include/extern.h +++ b/include/extern.h @@ -925,8 +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(init_random); -E void NDECL(reseed_random); +E void FDECL(init_random, (int FDECL((*fn), (int)))); +E void FDECL(reseed_random, (int FDECL((*fn), (int)))); E time_t NDECL(getnow); E int NDECL(getyear); #if 0 @@ -2105,7 +2105,7 @@ E void FDECL(genl_outrip, (winid, int, time_t)); /* ### rnd.c ### */ #ifdef USE_ISAAC64 -E void FDECL(init_isaac64, (unsigned long)); +E void FDECL(init_isaac64, (unsigned long, int FDECL((*fn), (int)))); E long NDECL(nhrand); #endif E int FDECL(rn2, (int)); diff --git a/src/detect.c b/src/detect.c index 545f3906e..13676f48a 100644 --- a/src/detect.c +++ b/src/detect.c @@ -869,10 +869,10 @@ int src_cursed; obj.ox = x; obj.oy = y; } - obj.otyp = !Hallucination ? GOLD_PIECE : random_object(); + obj.otyp = !Hallucination ? GOLD_PIECE : random_object(rn2_on_display_rng); obj.quan = (long) ((obj.otyp == GOLD_PIECE) ? rnd(10) : objects[obj.otyp].oc_merge ? rnd(2) : 1); - obj.corpsenm = random_monster(); /* if otyp == CORPSE */ + obj.corpsenm = random_monster(rn2); /* if otyp == CORPSE */ map_object(&obj, 1); } else if (trap) { map_trap(trap, 1); diff --git a/src/do.c b/src/do.c index ad2e3045d..7467356c7 100644 --- a/src/do.c +++ b/src/do.c @@ -1420,7 +1420,8 @@ boolean at_stairs, falling, portal; /* we'll reach here if running in wizard mode */ error("Cannot continue this game."); } - reseed_random(); + reseed_random(rn2); + reseed_random(rn2_on_display_rng); minit(); /* ZEROCOMP */ getlev(fd, hackpid, new_ledger, FALSE); (void) nhclose(fd); diff --git a/src/hacklib.c b/src/hacklib.c index 60f492b37..1fe5c8fd6 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -51,8 +51,8 @@ boolean fuzzymatch (const char *, const char *, const char *, boolean) void setrandom (void) - void init_random (void) - void reseed_random (void) + void init_random (fn) + void reseed_random (fn) time_t getnow (void) int getyear (void) char * yymmdd (time_t) @@ -851,12 +851,20 @@ extern struct tm *FDECL(localtime, (time_t *)); STATIC_DCL struct tm *NDECL(getlt); /* Sets the seed for the random number generator */ -static void -set_random(unsigned long seed) -{ #ifdef USE_ISAAC64 - init_isaac64(seed); -#else +static void +set_random(seed, fn) +unsigned long seed; +int FDECL((*fn), (int)); +{ + init_isaac64(seed, fn); +} +#else /* USE_ISAAC64 */ +static void +set_random(seed, fn) +unsigned long seed; +int FDECL((*fn),(int)); +{ /* the types are different enough here that sweeping the different * routine names into one via #defines is even more confusing */ @@ -877,8 +885,8 @@ set_random(unsigned long seed) # endif # endif # endif -#endif } +#endif /* USE_ISAAC64 */ /* An appropriate version of this must always be provided in port-specific code somewhere. It returns a number suitable @@ -890,19 +898,21 @@ extern unsigned long NDECL(sys_random_seed); * Only call once. */ void -init_random() +init_random(fn) +int FDECL((*fn),(int)); { - set_random(sys_random_seed()); + set_random(sys_random_seed(), fn); } /* Reshuffles the random number generator. */ void -reseed_random() +reseed_random(fn) +int FDECL((*fn),(int)); { /* only reseed if we are certain that the seed generation is unguessable * by the players. */ if (has_strong_rngseed) - init_random(); + init_random(fn); } time_t diff --git a/src/mklev.c b/src/mklev.c index 4cf5b9000..e2048aec8 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -982,7 +982,8 @@ mklev() struct mkroom *croom; int ridx; - reseed_random(); + reseed_random(rn2); + reseed_random(rn2_on_display_rng); init_mapseen(&u.uz); if (getbones()) @@ -1012,7 +1013,8 @@ mklev() for (ridx = 0; ridx < SIZE(rooms); ridx++) rooms[ridx].orig_rtype = rooms[ridx].rtype; - reseed_random(); + reseed_random(rn2); + reseed_random(rn2_on_display_rng); } void diff --git a/src/options.c b/src/options.c index 8fe27c8d4..77d6d6338 100644 --- a/src/options.c +++ b/src/options.c @@ -691,8 +691,9 @@ initoptions_init() /* set up the command parsing */ reset_commands(TRUE); /* init */ - /* initialize the random number generator */ - init_random(); + /* initialize the random number generator(s) */ + init_random(rn2); + init_random(rn2_on_display_rng); /* for detection of configfile options specified multiple times */ iflags.opt_booldup = iflags.opt_compdup = (int *) 0; diff --git a/src/zap.c b/src/zap.c index 95c5aaa2c..8c0219529 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1488,7 +1488,7 @@ int id; /* now change it into something laid by the hero */ while (tryct--) { - mnum = can_be_hatched(random_monster()); + mnum = can_be_hatched(random_monster(rn2)); if (mnum != NON_PM && !dead_species(mnum, TRUE)) { otmp->spe = 1; /* laid by hero */ set_corpsenm(otmp, mnum); /* also sets hatch timer */ From 54062e0ad62457e8bec161a6192d4d6894c521f1 Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 28 Jan 2019 19:54:18 -0500 Subject: [PATCH 17/18] include the rnd.c bits --- src/rnd.c | 79 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/src/rnd.c b/src/rnd.c index 551f33637..fa8ce0e20 100644 --- a/src/rnd.c +++ b/src/rnd.c @@ -7,28 +7,71 @@ #ifdef USE_ISAAC64 #include "isaac64.h" +#if 0 static isaac64_ctx rng_state; +#endif + +struct rnglist_t { + int FDECL((*fn), (int)); + boolean init; + isaac64_ctx rng_state; +}; + +enum {CORE = 0, DISP}; + +static struct rnglist_t rnglist[] = { + {rn2, FALSE, {0}}, /* CORE */ + {rn2_on_display_rng, FALSE, {0}}, /* DISP */ +}; + +int +whichrng(fn) +int (*fn)(int); +{ + int i; + + for (i = 0; i < SIZE(rnglist); ++i) + if (rnglist[i].fn == fn) + return i; + return -1; +} void -init_isaac64(unsigned long seed) +init_isaac64(seed, fn) +unsigned long seed; +int FDECL((*fn),(int)); { unsigned char new_rng_state[sizeof(seed)]; - int i; + int i, rngindx = whichrng(fn); + + if (rngindx < 0) + panic("Bad rng function passed to init_isaac64()."); + for (i=0; i>= 8; } - - isaac64_init(&rng_state, new_rng_state, sizeof(seed)); + isaac64_init(&rnglist[rngindx].rng_state, new_rng_state, sizeof(seed)); } static int RND(int x) { - return (isaac64_next_uint64(&rng_state) % x); + return (isaac64_next_uint64(&rnglist[CORE].rng_state) % x); } -#else +/* 0 <= rn2(x) < x, but on a different sequence from the "main" rn2; + used in cases where the answer doesn't affect gameplay and we don't + want to give users easy control over the main RNG sequence. */ +int +rn2_on_display_rng(x) +register int x; +{ + return (isaac64_next_uint64(&rnglist[DISP].rng_state) % x); +} + +#else /* USE_ISAAC64 */ + /* "Rand()"s definition is determined by [OS]conf.h */ #if defined(LINT) && defined(UNIX) /* rand() is long... */ extern int NDECL(rand); @@ -41,7 +84,15 @@ extern int NDECL(rand); #define RND(x) ((int) ((Rand() >> 3) % (x))) #endif #endif /* LINT */ -#endif +int +rn2_on_display_rng(x) +register int x; +{ + static unsigned seed = 1; + seed *= 2739110765; + return (int)((seed >> 16) % (unsigned)x); +} +#endif /* USE_ISAAC64 */ /* 0 <= rn2(x) < x */ int @@ -60,20 +111,6 @@ register int x; #endif } -/* 0 <= rn2(x) < x, but on a different sequence from the "main" rn2; - used in cases where the answer doesn't affect gameplay and we don't - want to give users easy control over the main RNG sequence. This is - an intentionally low-quality RNG to discourage its use for anything - gameplay-affecting; please use a better RNG in that case. */ -int -rn2_on_display_rng(x) -register int x; -{ - static unsigned seed = 1; - seed *= 2739110765; - return (int)((seed >> 16) % (unsigned)x); -} - /* 0 <= rnl(x) < x; sometimes subtracting Luck; good luck approaches 0, bad luck approaches (x-1) */ int From 0c96dd6a2280219105e4b77e6f6414afb7756af9 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 29 Jan 2019 03:37:08 +0000 Subject: [PATCH 18/18] Consistently use rn2 in trap detection It's a gameplay-affecting action (it updates the character's memory of the map), and there's no way to spam it without using resources, so rn2 is safe. --- src/detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detect.c b/src/detect.c index 13676f48a..3a25d45fb 100644 --- a/src/detect.c +++ b/src/detect.c @@ -869,7 +869,7 @@ int src_cursed; obj.ox = x; obj.oy = y; } - obj.otyp = !Hallucination ? GOLD_PIECE : random_object(rn2_on_display_rng); + obj.otyp = !Hallucination ? GOLD_PIECE : random_object(rn2); obj.quan = (long) ((obj.otyp == GOLD_PIECE) ? rnd(10) : objects[obj.otyp].oc_merge ? rnd(2) : 1); obj.corpsenm = random_monster(rn2); /* if otyp == CORPSE */