diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 03c0b824e..3f2c55378 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -48,6 +48,7 @@ Platform- and/or Interface-Specific New Features NetHack Community Patches (or Variation) Included ------------------------------------------------- +hallucinatory trap names from github pull request #174 autounlock feature originally from unnethack in github pull request #228 diff --git a/include/display.h b/include/display.h index 4bece448b..2a2e56bae 100644 --- a/include/display.h +++ b/include/display.h @@ -149,25 +149,21 @@ /* * random_monster() * random_object() - * random_trap() * - * Respectively return a random monster, object, or trap number. + * Respectively return a random monster or object. */ #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() * what_mon() - * what_trap() * * If hallucinating, choose a random object/monster, otherwise, use the one * given. Use the given rng to handle hallucination. */ #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 @@ -338,8 +334,8 @@ #define explosion_to_glyph(expltype, idx) \ ((((expltype) * MAXEXPCHARS) + ((idx) - S_explode1)) + GLYPH_EXPLODE_OFF) -#define trap_to_glyph(trap, rng) \ - cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp, rng))) +#define trap_to_glyph(trap) \ + cmap_to_glyph(trap_to_defsym((trap)->ttyp)) /* 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 9a6b8b476..d32bb14d0 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2653,6 +2653,7 @@ E boolean FDECL(uescaped_shaft, (struct trap *)); E boolean NDECL(lava_effects); E void NDECL(sink_into_lava); E void NDECL(sokoban_guilt); +E const char * FDECL(trapname, (int, BOOLEAN_P)); /* ### u_init.c ### */ diff --git a/src/apply.c b/src/apply.c index 27529054d..ff9de0495 100644 --- a/src/apply.c +++ b/src/apply.c @@ -2516,7 +2516,7 @@ struct obj *otmp; if (otmp == g.trapinfo.tobj && u.ux == g.trapinfo.tx && u.uy == g.trapinfo.ty) { You("resume setting %s%s.", shk_your(buf, otmp), - defsyms[trap_to_defsym(what_trap(ttyp, rn2))].explanation); + trapname(ttyp, FALSE)); set_occupation(set_trap, occutext, 0); return; } @@ -2541,8 +2541,7 @@ 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, rn2))] - .explanation)); + the(trapname(ttyp, FALSE))); if (yn(buf) == 'y') { if (chance) { switch (ttyp) { @@ -2552,9 +2551,7 @@ struct obj *otmp; break; case BEAR_TRAP: /* drop it without arming it */ reset_trapset(); - You("drop %s!", - the(defsyms[trap_to_defsym(what_trap(ttyp, rn2))] - .explanation)); + You("drop %s!", the(trapname(ttyp, FALSE))); dropx(otmp); return; } @@ -2564,8 +2561,7 @@ struct obj *otmp; return; } } - You("begin setting %s%s.", shk_your(buf, otmp), - defsyms[trap_to_defsym(what_trap(ttyp, rn2))].explanation); + You("begin setting %s%s.", shk_your(buf, otmp), trapname(ttyp, FALSE)); set_occupation(set_trap, occutext, 0); return; } @@ -2596,8 +2592,7 @@ set_trap() add_damage(u.ux, u.uy, 0L); /* schedule removal */ } if (!g.trapinfo.force_bungle) - You("finish arming %s.", - the(defsyms[trap_to_defsym(what_trap(ttyp, rn2))].explanation)); + You("finish arming %s.", the(trapname(ttyp, FALSE))); if (((otmp->cursed || Fumbling) && (rnl(10) > 5)) || g.trapinfo.force_bungle) dotrap(ttmp, diff --git a/src/cmd.c b/src/cmd.c index 31b3397c7..df3646be4 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -2513,7 +2513,7 @@ int final; Strcpy(predicament, "trapped"); if ((t = t_at(u.ux, u.uy)) != 0) Sprintf(eos(predicament), " in %s", - an(defsyms[trap_to_defsym(t->ttyp)].explanation)); + an(trapname(t->ttyp, FALSE))); } if (u.usteed) { /* not `Riding' here */ Sprintf(buf, "%s%s ", anchored ? "you and " : "", steedname); diff --git a/src/detect.c b/src/detect.c index e35d3829a..4e04d3f64 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1612,7 +1612,6 @@ void find_trap(trap) struct trap *trap; { - int tt = what_trap(trap->ttyp, rn2); boolean cleared = FALSE; trap->tseen = 1; @@ -1623,8 +1622,7 @@ struct trap *trap; 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)) { + levl[trap->tx][trap->ty].glyph != trap_to_glyph(trap)) { /* There's too much clutter to see your find otherwise */ cls(); map_trap(trap, 1); @@ -1632,7 +1630,7 @@ struct trap *trap; cleared = TRUE; } - You("find %s.", an(defsyms[trap_to_defsym(tt)].explanation)); + You("find %s.", an(trapname(trap->ttyp, FALSE))); if (cleared) { display_nhwindow(WIN_MAP, TRUE); /* wait */ @@ -1871,7 +1869,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, rn2_on_display_rng); + glyph = trap_to_glyph(t); } if ((glyph_is_object(glyph) && !keep_objs) || (glyph_is_trap(glyph) && !keep_traps) diff --git a/src/dig.c b/src/dig.c index 5548ce19c..802af8968 100644 --- a/src/dig.c +++ b/src/dig.c @@ -579,7 +579,7 @@ int ttyp; if (ttyp != PIT && (!Can_dig_down(&u.uz) && !lev->candig)) { impossible("digactualhole: can't dig %s on this level.", - defsyms[trap_to_defsym(ttyp)].explanation); + trapname(ttyp, TRUE)); ttyp = PIT; } diff --git a/src/display.c b/src/display.c index 5a6369ec2..35e1f41a0 100644 --- a/src/display.c +++ b/src/display.c @@ -229,7 +229,7 @@ register struct trap *trap; register int show; { register int x = trap->tx, y = trap->ty; - register int glyph = trap_to_glyph(trap, newsym_rn2); + register int glyph = trap_to_glyph(trap); if (g.level.flags.hero_memory) levl[x][y].glyph = glyph; diff --git a/src/dothrow.c b/src/dothrow.c index 8bf4d7de8..6f401e0d1 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -756,8 +756,7 @@ int x, y; return TRUE; } else { if (ttmp->tseen) - You("pass right over %s.", - an(defsyms[trap_to_defsym(ttmp->ttyp)].explanation)); + You("pass right over %s.", an(trapname(ttmp->ttyp, FALSE))); } } if (--*range < 0) /* make sure our range never goes negative */ diff --git a/src/hack.c b/src/hack.c index 9715c8285..d15ca467c 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1499,10 +1499,8 @@ domove_core() if (g.context.run >= 2) { if (iflags.mention_walls) { if (trap && trap->tseen) { - int tt = what_trap(trap->ttyp, rn2_on_display_rng); - You("stop in front of %s.", - an(defsyms[trap_to_defsym(tt)].explanation)); + an(trapname(trap->ttyp, FALSE))); } else if (is_pool_or_lava(x,y) && levl[x][y].seenv) { You("stop at the edge of the %s.", hliquid(is_pool(x,y) ? "water" : "lava")); @@ -2758,10 +2756,9 @@ 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, rn2_on_display_rng); You("stop in front of %s.", - an(defsyms[trap_to_defsym(tt)].explanation)); + an(trapname(trap->ttyp, FALSE))); } goto stop; } diff --git a/src/invent.c b/src/invent.c index cc6bd353c..0089cd7ac 100644 --- a/src/invent.c +++ b/src/invent.c @@ -3422,8 +3422,7 @@ boolean picked_some; return !!Blind; } if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen) - There("is %s here.", - an(defsyms[trap_to_defsym(trap->ttyp)].explanation)); + There("is %s here.", an(trapname(trap->ttyp, FALSE))); otmp = g.level.objects[u.ux][u.uy]; dfeature = dfeature_at(u.ux, u.uy, fbuf2); diff --git a/src/objnam.c b/src/objnam.c index bae9e5974..50f64ebb7 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -3484,10 +3484,8 @@ struct obj *no_wish; goto typfnd; } else if (trapped == 1 || *zp != '\0') { /* "trapped " or " trap" (actually "*") */ - int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE); - /* use canonical trap spelling, skip object matching */ - Strcpy(bp, defsyms[idx].explanation); + Strcpy(bp, trapname(beartrap ? BEAR_TRAP : LANDMINE, TRUE)); goto wiztrap; } /* [no prefix or suffix; we're going to end up matching @@ -3692,7 +3690,7 @@ struct obj *no_wish; struct trap *t; const char *tname; - tname = defsyms[trap_to_defsym(trap)].explanation; + tname = trapname(trap, TRUE); if (strncmpi(tname, bp, strlen(tname))) continue; /* found it; avoid stupid mistakes */ @@ -3700,7 +3698,7 @@ struct obj *no_wish; trap = ROCKTRAP; if ((t = maketrap(x, y, trap)) != 0) { trap = t->ttyp; - tname = defsyms[trap_to_defsym(trap)].explanation; + tname = trapname(trap, TRUE); pline("%s%s.", An(tname), (trap != MAGIC_PORTAL) ? "" : " to nowhere"); } else diff --git a/src/pager.c b/src/pager.c index f29cedadb..140769c64 100644 --- a/src/pager.c +++ b/src/pager.c @@ -305,8 +305,7 @@ int x, y; /* newsym lets you know of the trap, so mention it here */ if (tt == BEAR_TRAP || is_pit(tt) || tt == WEB) { - Sprintf(eos(buf), ", trapped in %s", - an(defsyms[trap_to_defsym(tt)].explanation)); + Sprintf(eos(buf), ", trapped in %s", an(trapname(tt, FALSE))); t->tseen = 1; } } @@ -458,7 +457,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), rn2_on_display_rng); + int tnum = glyph_to_trap(glyph); /* Trap detection displays a bear trap at locations having * a trapped door or trapped container or both. @@ -470,7 +469,7 @@ char *buf, *monbuf; else if (trapped_door_at(tnum, x, y)) Strcpy(buf, "trapped door"); /* not "trap door"... */ else - Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation); + Strcpy(buf, trapname(tnum, FALSE)); } else if (glyph_is_warning(glyph)) { int warnindx = glyph_to_warning(glyph); @@ -1570,9 +1569,8 @@ doidtrap() if (u.dz < 0 ? is_hole(tt) : tt == ROCKTRAP) break; } - tt = what_trap(tt, rn2_on_display_rng); pline("That is %s%s%s.", - an(defsyms[trap_to_defsym(tt)].explanation), + an(trapname(tt, FALSE)), !trap->madeby_u ? "" : (tt == WEB) diff --git a/src/steed.c b/src/steed.c index f8e680d7d..5e92adf67 100644 --- a/src/steed.c +++ b/src/steed.c @@ -285,7 +285,7 @@ boolean force; /* Quietly force this animal */ struct trap *t = t_at(mtmp->mx, mtmp->my); You_cant("mount %s while %s's trapped in %s.", mon_nam(mtmp), - mhe(mtmp), an(defsyms[trap_to_defsym(t->ttyp)].explanation)); + mhe(mtmp), an(trapname(t->ttyp, FALSE))); return (FALSE); } diff --git a/src/trap.c b/src/trap.c index 0c8936fa3..2b6633e94 100644 --- a/src/trap.c +++ b/src/trap.c @@ -923,14 +923,14 @@ unsigned trflags; */ pline("Air currents pull you down into %s %s!", a_your[trap->madeby_u], - defsyms[trap_to_defsym(ttype)].explanation); + trapname(ttype, TRUE)); /* do force "pit" while hallucinating */ /* then proceed to normal trap effect */ } else if (already_seen && !forcetrap) { if ((Levitation || (Flying && !plunged)) && (is_pit(ttype) || ttype == HOLE || ttype == BEAR_TRAP)) { You("%s over %s %s.", Levitation ? "float" : "fly", a_your[trap->madeby_u], - defsyms[trap_to_defsym(ttype)].explanation); + trapname(ttype, FALSE)); return; } if (!Fumbling && ttype != MAGIC_PORTAL && ttype != VIBRATING_SQUARE @@ -941,7 +941,7 @@ unsigned trflags; You("escape %s %s.", (ttype == ARROW_TRAP && !trap->madeby_u) ? "an" : a_your[trap->madeby_u], - defsyms[trap_to_defsym(ttype)].explanation); + trapname(ttype, FALSE)); return; } } @@ -1290,7 +1290,7 @@ unsigned trflags; if (!Can_fall_thru(&u.uz)) { seetrap(trap); /* normally done in fall_through */ impossible("dotrap: %ss cannot exist on this level.", - defsyms[trap_to_defsym(ttype)].explanation); + trapname(ttype, TRUE)); break; /* don't activate it after all */ } fall_through(TRUE, (trflags & TOOKPLUNGE)); @@ -2465,7 +2465,7 @@ register struct monst *mtmp; case TRAPDOOR: if (!Can_fall_thru(&u.uz)) { impossible("mintrap: %ss cannot exist on this level.", - defsyms[trap_to_defsym(tt)].explanation); + trapname(tt, TRUE)); break; /* don't activate it after all */ } if (is_flyer(mptr) || is_floater(mptr) || mptr == &mons[PM_WUMPUS] @@ -4051,8 +4051,7 @@ boolean force_failure; if ((g.invent && (inv_weight() + weight_cap() > 600)) || bigmonst(g.youmonst.data)) { /* don't allow untrap if they can't get thru to it */ - You("are unable to reach the %s!", - defsyms[trap_to_defsym(ttype)].explanation); + You("are unable to reach the %s!", trapname(ttype, FALSE)); return 0; } } @@ -4061,8 +4060,7 @@ boolean force_failure; if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) rider_cant_reach(); else - You("are unable to reach the %s!", - defsyms[trap_to_defsym(ttype)].explanation); + You("are unable to reach the %s!", trapname(ttype, FALSE)); return 0; } @@ -4102,7 +4100,7 @@ boolean force_failure; } else { pline("%s %s is difficult to %s.", ttmp->madeby_u ? "Your" : under_u ? "This" : "That", - defsyms[trap_to_defsym(ttype)].explanation, + trapname(ttype, FALSE), (ttype == WEB) ? "remove" : "disarm"); } return 1; @@ -4381,7 +4379,7 @@ boolean force; ttmp = t_at(x, y); if (ttmp && !ttmp->tseen) ttmp = 0; - trapdescr = ttmp ? defsyms[trap_to_defsym(ttmp->ttyp)].explanation : 0; + trapdescr = ttmp ? trapname(ttmp->ttyp, FALSE) : 0; here = (x == u.ux && y == u.uy); /* !u.dx && !u.dy */ if (here) /* are there are one or more containers here? */ @@ -4641,7 +4639,7 @@ boolean *noticed; /* set to true iff hero notices the effect; */ } if (!trapdescr) - trapdescr = defsyms[trap_to_defsym(t->ttyp)].explanation; + trapdescr = trapname(t->ttyp, FALSE); if (!which) which = t->tseen ? the_your[t->madeby_u] : index(vowels, *trapdescr) ? "an" : "a"; @@ -5452,4 +5450,55 @@ maybe_finish_sokoban() } } +/* Return the string name of the trap type passed in, unless the player is + * hallucinating, in which case return a random or hallucinatory trap name. + * If the second argument is true, return the correct trap name even when + * hallucinating (for things like wizard mode wishing for traps and impossible + * calls). + * Originally I had intended for messages like "You begin setting the bear trap" + * to override as well, but the context in those bits of code indicated that it + * was meant to take a random name if the hero was hallucinating. + */ +const char * +trapname(ttyp, override) +int ttyp; +boolean override; +{ + const char * halu_trapnames[] = { + /* riffs on actual nethack traps */ + "bottomless pit", "polymorphism trap", "devil teleporter", + "falling boulder trap", "anti-anti-magic field", "weeping gas trap", + "queasy board", "electrified web", "owlbear trap", "sand mine", + /* some traps found in nethack variants */ + "death trap", "disintegration trap", "ice trap", "monochrome trap", + /* plausible real-life traps */ + "axeblade trap", "pool of boiling oil", "pool of quicksand", + "field of caltrops", "buzzsaw trap", "spiked floor", "revolving wall", + "uneven floor", "finger trap", "jack-in-a-box", "yellow snow", + "booby trap", "rat trap", "poisoned nail", "snare", "whirlpool", + "trip wire", + /* sci-fi */ + "negative space", "tensor field", "singularity", "imperial fleet", + "black hole", "thermal detonator", "event horizon", + "entoptic phenomenon", + /* miscellaneous suggestions */ + "sweet-smelling gas vent", "phone booth", "exploding runes", + "never-ending elevator", "slime pit", "warp zone", "illusory floor", + "pile of poo", "honey trap", "tourist trap" + }; + int total_names = TRAPNUM + SIZE(halu_trapnames); + int nameidx = rn2_on_display_rng(total_names); + if (override || !Hallucination) { + return defsyms[trap_to_defsym(ttyp)].explanation; + } + if (nameidx < TRAPNUM) { + /* random but real trap name */ + return defsyms[trap_to_defsym(nameidx)].explanation; + } + else { + nameidx -= TRAPNUM; + return halu_trapnames[nameidx]; + } +} + /*trap.c*/