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;