Merge branch 'NetHack-3.7' of https://rodney.nethack.org:20040/git/NHsource into NetHack-3.7

This commit is contained in:
Alex Smith
2020-03-18 23:02:04 +00:00
30 changed files with 235 additions and 367 deletions
+4 -8
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 allmain.c $NHDT-Date: 1580044340 2020/01/26 13:12:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.138 $ */
/* NetHack 3.6 allmain.c $NHDT-Date: 1584405115 2020/03/17 00:31:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.143 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -178,6 +178,9 @@ boolean resuming;
g.monstermoves++; /* [obsolete (for a long time...)] */
g.moves++;
if (flags.time && !g.context.run)
iflags.time_botl = TRUE; /* 'moves' just changed */
/********************************/
/* once-per-turn things go here */
/********************************/
@@ -189,8 +192,6 @@ boolean resuming;
if (u.ublesscnt)
u.ublesscnt--;
if (flags.time && !g.context.run)
iflags.time_botl = TRUE;
/* One possible result of prayer is healing. Whether or
* not you get healed depends on your current hit points.
@@ -436,8 +437,6 @@ boolean resuming;
if (!g.multi) {
/* lookaround may clear multi */
g.context.move = 0;
if (flags.time)
g.context.botl = TRUE;
continue;
}
if (g.context.mv) {
@@ -457,9 +456,6 @@ boolean resuming;
}
if (u.utotype) /* change dungeon level */
deferred_goto(); /* after rhack() */
/* !g.context.move here: multiple movement command stopped */
else if (flags.time && (!g.context.move || !g.context.mv))
g.context.botl = TRUE;
if (g.vision_full_recalc)
vision_recalc(0); /* vision! */
+5 -4
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 botl.c $NHDT-Date: 1583190980 2020/03/02 23:16:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.185 $ */
/* NetHack 3.6 botl.c $NHDT-Date: 1584350350 2020/03/16 09:19:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.186 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1117,10 +1117,11 @@ cond_menu(VOID_ARGS)
} while (showmenu);
if (res > 0) {
for (i = 0; i < CONDITION_COUNT; ++i) {
if (condtests[i].enabled != condtests[i].choice)
for (i = 0; i < CONDITION_COUNT; ++i)
if (condtests[i].enabled != condtests[i].choice) {
condtests[i].enabled = condtests[i].choice;
}
g.context.botl = TRUE;
}
}
}
+7 -5
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 dig.c $NHDT-Date: 1578659784 2020/01/10 12:36:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.135 $ */
/* NetHack 3.6 dig.c $NHDT-Date: 1584350347 2020/03/16 09:19:07 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.138 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -928,7 +928,7 @@ coord *cc;
case 1:
You("unearth a corpse.");
if ((otmp = mk_tt_object(CORPSE, dig_x, dig_y)) != 0)
otmp->age -= 100; /* this is an *OLD* corpse */
otmp->age -= (TAINT_AGE + 1); /* this is an *OLD* corpse */
break;
case 2:
if (!Blind)
@@ -1409,7 +1409,10 @@ zap_dig()
if (is_animal(mtmp->data))
You("pierce %s %s wall!", s_suffix(mon_nam(mtmp)),
mbodypart(mtmp, STOMACH));
mtmp->mhp = 1; /* almost dead */
if (unique_corpstat(mtmp->data))
mtmp->mhp = (mtmp->mhp + 1) / 2;
else
mtmp->mhp = 1; /* almost dead */
expels(mtmp, mtmp->data, !is_animal(mtmp->data));
}
return;
@@ -1827,8 +1830,7 @@ boolean *dealloced;
*dealloced = FALSE;
if (otmp == uball) {
unpunish();
u.utrap = rn1(50, 20);
u.utraptype = TT_BURIEDBALL;
set_utrap((unsigned) rn1(50, 20), TT_BURIEDBALL);
pline_The("iron ball gets buried!");
}
/* after unpunish(), or might get deallocated chain */
+4 -9
View File
@@ -1461,12 +1461,14 @@ boolean at_stairs, falling, portal;
if (!(g.level_info[new_ledger].flags & LFILE_EXISTS)) {
/* entering this level for first time; make it now */
if (g.level_info[new_ledger].flags & (FORGOTTEN | VISITED)) {
if (g.level_info[new_ledger].flags & (VISITED)) {
impossible("goto_level: returning to discarded level?");
g.level_info[new_ledger].flags &= ~(FORGOTTEN | VISITED);
g.level_info[new_ledger].flags &= ~(VISITED);
}
mklev();
new = TRUE; /* made the level */
familiar = (find_ghost_with_name(g.plname) != (struct monst *) 0);
} else {
/* returning to previously visited level; reload it */
nhfp = open_levelfile(new_ledger, whynot);
@@ -1606,13 +1608,6 @@ boolean at_stairs, falling, portal;
else if (Is_firelevel(&u.uz))
fumaroles();
if (g.level_info[new_ledger].flags & FORGOTTEN) {
forget_map(ALL_MAP); /* forget the map */
forget_traps(); /* forget all traps too */
familiar = TRUE;
g.level_info[new_ledger].flags &= ~FORGOTTEN;
}
/* Reset the screen. */
vision_reset(); /* reset the blockages */
g.glyphmap_perlevel_flags = 0L; /* force per-level mapglyph() changes */
+4
View File
@@ -1181,6 +1181,10 @@ int after; /* this is extra fast monster movement */
}
}
}
/* pet moved when attacking */
if (mtmp->mx != omx || mtmp->my != omy)
return 0;
}
}
+4 -3
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 dothrow.c $NHDT-Date: 1583073990 2020/03/01 14:46:30 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.183 $ */
/* NetHack 3.6 dothrow.c $NHDT-Date: 1584398443 2020/03/16 22:40:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.184 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -714,8 +714,9 @@ int x, y;
}
}
/* Caller has already determined that dragging the ball is allowed */
if (Punished && uball->where == OBJ_FLOOR) {
/* caller has already determined that dragging the ball is allowed;
if ball is carried we might still need to drag the chain */
if (Punished) {
int bc_control;
xchar ballx, bally, chainx, chainy;
boolean cause_delay;
+3 -32
View File
@@ -1958,7 +1958,7 @@ const char *nam;
&& dlev.dnum == valley_level.dnum))
&& (/* either wizard mode or else seen and not forgotten */
wizard
|| (g.level_info[idx].flags & (FORGOTTEN | VISITED))
|| (g.level_info[idx].flags & (VISITED))
== VISITED)) {
lev = depth(&dlev);
}
@@ -1973,9 +1973,9 @@ const char *nam;
idx &= 0x00FF;
/* either wizard mode, or else _both_ sides of branch seen */
if (wizard
|| (((g.level_info[idx].flags & (FORGOTTEN | VISITED))
|| (((g.level_info[idx].flags & (VISITED))
== VISITED)
&& ((g.level_info[idxtoo].flags & (FORGOTTEN | VISITED))
&& ((g.level_info[idxtoo].flags & (VISITED))
== VISITED))) {
if (ledger_to_dnum(idxtoo) == u.uz.dnum)
idx = idxtoo;
@@ -2392,35 +2392,6 @@ const char *s;
}
void
forget_mapseen(ledger_num)
int ledger_num;
{
mapseen *mptr;
struct cemetery *bp;
for (mptr = g.mapseenchn; mptr; mptr = mptr->next)
if (g.dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel
== ledger_num)
break;
/* if not found, then nothing to forget */
if (mptr) {
mptr->flags.forgot = 1;
mptr->br = (branch *) 0;
/* custom names are erased, not just forgotten until revisited */
if (mptr->custom) {
mptr->custom_lth = 0;
free((genericptr_t) mptr->custom);
mptr->custom = (char *) 0;
}
(void) memset((genericptr_t) mptr->msrooms, 0, sizeof mptr->msrooms);
for (bp = mptr->final_resting_place; bp; bp = bp->next)
bp->bonesknown = FALSE;
}
}
void
rm_mapseen(ledger_num)
int ledger_num;
+11 -13
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 eat.c $NHDT-Date: 1577190688 2019/12/24 12:31:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.222 $ */
/* NetHack 3.6 eat.c $NHDT-Date: 1584405116 2020/03/17 00:31:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.223 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -3056,17 +3056,16 @@ boolean incr;
switch (newhs) {
case HUNGRY:
if (Hallucination) {
You((!incr) ? "now have a lesser case of the munchies."
: "are getting the munchies.");
You(!incr ? "now have a lesser case of the munchies."
: "are getting the munchies.");
} else
You((!incr) ? "only feel hungry now."
: (u.uhunger < 145)
? "feel hungry."
: "are beginning to feel hungry.");
You(!incr ? "only feel hungry now."
: (u.uhunger < 145) ? "feel hungry."
: "are beginning to feel hungry.");
if (incr && g.occupation
&& (g.occupation != eatfood && g.occupation != opentin))
stop_occupation();
g.context.travel = g.context.travel1 = g.context.mv = g.context.run = 0;
end_running(TRUE);
break;
case WEAK:
if (Hallucination)
@@ -3079,14 +3078,13 @@ boolean incr;
? g.urole.name.m
: "Elf");
else
You((!incr)
? "feel weak now."
: (u.uhunger < 45) ? "feel weak."
: "are beginning to feel weak.");
You(!incr ? "feel weak now."
: (u.uhunger < 45) ? "feel weak."
: "are beginning to feel weak.");
if (incr && g.occupation
&& (g.occupation != eatfood && g.occupation != opentin))
stop_occupation();
g.context.travel = g.context.travel1 = g.context.mv = g.context.run = 0;
end_running(TRUE);
break;
}
u.uhs = newhs;
+35 -11
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 hack.c $NHDT-Date: 1582799171 2020/02/27 10:26:11 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.249 $ */
/* NetHack 3.6 hack.c $NHDT-Date: 1584405116 2020/03/17 00:31:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.250 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -954,7 +954,7 @@ int mode;
if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && g.context.travel1
&& distmin(u.ux, u.uy, u.tx, u.ty) == 1
&& !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
g.context.run = 0;
end_running(FALSE);
if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
if (mode == TRAVP_TRAVEL) {
u.dx = u.tx - u.ux;
@@ -1964,10 +1964,14 @@ domove_core()
}
if (g.context.run && flags.runmode != RUN_TPORT) {
/* display every step or every 7th step depending upon mode */
/* for tport mode, don't display anything until we've stopped;
for normal (leap) mode, update display every 7th step
(relative to turn counter; ought to be to start of running);
for walk and crawl (visual debugging) modes, update the
display after every step */
if (flags.runmode != RUN_LEAP || !(g.moves % 7L)) {
if (flags.time)
iflags.time_botl = 1;
/* moveloop() suppresses time_botl when running */
iflags.time_botl = flags.time;
curs_on_u();
delay_output();
if (flags.runmode == RUN_CRAWL) {
@@ -2927,6 +2931,21 @@ monster_nearby()
return 0;
}
void
end_running(and_travel)
boolean and_travel;
{
/* moveloop() suppresses time_botl when context.run is non-zero; when
running stops, update 'time' even if other botl status is unchanged */
if (flags.time && g.context.run)
iflags.time_botl = TRUE;
g.context.run = 0;
/* 'context.mv' isn't travel but callers who want to end travel
all clear it too */
if (and_travel)
g.context.travel = g.context.travel1 = g.context.mv = 0;
}
void
nomul(nval)
int nval;
@@ -2939,7 +2958,7 @@ int nval;
g.multi = nval;
if (nval == 0)
g.multi_reason = NULL;
g.context.travel = g.context.travel1 = g.context.mv = g.context.run = 0;
end_running(TRUE);
}
/* called when a non-movement, multi-turn action has completed */
@@ -2947,7 +2966,7 @@ void
unmul(msg_override)
const char *msg_override;
{
g.context.botl = 1;
g.context.botl = TRUE;
g.multi = 0; /* caller will usually have done this already */
if (msg_override)
g.nomovemsg = msg_override;
@@ -3018,11 +3037,19 @@ register int n;
register const char *knam;
boolean k_format;
{
#if 0 /* code below is prepared to handle negative 'loss' so don't add this
* until we've verified that no callers intentionally rely on that */
if (n <= 0) {
impossible("hero losing %d hit points due to \"%s\"?", n, knam);
return;
}
#endif
g.context.botl = TRUE; /* u.uhp or u.mh is changing */
end_running(TRUE);
if (Upolyd) {
u.mh -= n;
if (u.mhmax < u.mh)
u.mhmax = u.mh;
g.context.botl = 1;
if (u.mh < 1)
rehumanize();
else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
@@ -3033,9 +3060,6 @@ boolean k_format;
u.uhp -= n;
if (u.uhp > u.uhpmax)
u.uhpmax = u.uhp; /* perhaps n was negative */
else
g.context.travel = g.context.travel1 = g.context.mv = g.context.run = 0;
g.context.botl = 1;
if (u.uhp < 1) {
g.killer.format = k_format;
if (g.killer.name != knam) /* the thing that killed you */
+20
View File
@@ -73,6 +73,7 @@
void strbuf_nl_to_crlf (strbuf_t *)
char * nonconst (const char *, char *)
int swapbits (int, int, int)
UNUSED void shuffle_int_array (int *, int)
=*/
#ifdef LINT
#define Static /* pacify lint */
@@ -1301,4 +1302,23 @@ int val, bita, bitb;
return (val ^ ((tmp << bita) | (tmp << bitb)));
}
#if 0
/* randomize the given list of numbers 0 <= i < count */
static void
shuffle_int_array(indices, count)
int *indices;
int count;
{
int i, iswap, temp;
for (i = count - 1; i > 0; i--) {
if ((iswap = rn2(i + 1)) == i)
continue;
temp = indices[i];
indices[i] = indices[iswap];
indices[iswap] = temp;
}
}
#endif
/*hacklib.c*/
-2
View File
@@ -1175,8 +1175,6 @@ register struct attack *mattk;
}
/* adjattrib gives dunce cap message when appropriate */
(void) adjattrib(A_INT, -rnd(2), FALSE);
forget_levels(25); /* lose memory of 25% of levels */
forget_objects(25); /* lose memory of 25% of objects */
break;
case AD_PLYS:
hitmsg(mtmp, mattk);
+1 -1
View File
@@ -1543,7 +1543,7 @@ coord *tm;
otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], m.x, m.y,
CORPSTAT_INIT);
if (otmp)
otmp->age -= 51; /* died too long ago to eat */
otmp->age -= (TAINT_AGE + 1); /* died too long ago to eat */
}
}
-4
View File
@@ -1189,10 +1189,6 @@ struct obj *body;
int rot_adjust;
short action;
#define TAINT_AGE (50L) /* age when corpses go bad */
#define TROLL_REVIVE_CHANCE 37 /* 1/37 chance for 50 turns ~ 75% chance */
#define ROT_AGE (250L) /* age when corpses rot away */
/* lizards and lichen don't rot or revive */
if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN)
return;
+18 -2
View File
@@ -350,7 +350,7 @@ unsigned corpseflags;
num = undead_to_corpse(mndx);
corpstatflags |= CORPSTAT_INIT;
obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
obj->age -= 100; /* this is an *OLD* corpse */
obj->age -= (TAINT_AGE + 1); /* this is an *OLD* corpse */
break;
case PM_KOBOLD_MUMMY:
case PM_DWARF_MUMMY:
@@ -371,7 +371,7 @@ unsigned corpseflags;
num = undead_to_corpse(mndx);
corpstatflags |= CORPSTAT_INIT;
obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
obj->age -= 100; /* this is an *OLD* corpse */
obj->age -= (TAINT_AGE + 1); /* this is an *OLD* corpse */
break;
case PM_IRON_GOLEM:
num = d(2, 6);
@@ -4170,6 +4170,22 @@ pacify_guards()
}
}
struct monst *
find_ghost_with_name(str)
char *str;
{
struct monst *mtmp;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)
|| mtmp->data != &mons[PM_GHOST] || !has_mname(mtmp))
continue;
if (!strcmpi(MNAME(mtmp), str))
return mtmp;
}
return (struct monst *) 0;
}
void
mimic_hit_msg(mtmp, otyp)
struct monst *mtmp;
+1
View File
@@ -757,6 +757,7 @@ const char *in_str;
/* Hyphenated names -- it would be nice to handle these via
fuzzymatch() but it isn't able to ignore trailing stuff */
{ "ki rin", PM_KI_RIN },
{ "kirin", PM_KI_RIN },
{ "uruk hai", PM_URUK_HAI },
{ "orc captain", PM_ORC_CAPTAIN },
{ "woodland elf", PM_WOODLAND_ELF },
+3 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 options.c $NHDT-Date: 1583282760 2020/03/04 00:46:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.457 $ */
/* NetHack 3.7 options.c $NHDT-Date: 1584350350 2020/03/16 09:19:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.459 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2008. */
/* NetHack may be freely redistributed. See license for details. */
@@ -7568,6 +7568,8 @@ doset() /* changing options via menu by Per Liboriussen */
check_gold_symbol();
reglyph_darkroom();
(void) doredraw();
} else if (g.context.botl || g.context.botlx) {
bot();
}
return 0;
}
+5 -200
View File
@@ -22,11 +22,6 @@ static char *FDECL(apron_text, (struct obj *, char *buf));
static void FDECL(stripspe, (struct obj *));
static void FDECL(p_glow1, (struct obj *));
static void FDECL(p_glow2, (struct obj *, const char *));
static void FDECL(forget_single_object, (int));
#if 0 /* not used */
static void FDECL(forget_objclass, (int));
#endif
static void FDECL(randomize, (int *, int));
static void FDECL(forget, (int));
static int FDECL(maybe_tame, (struct monst *, struct obj *));
static boolean FDECL(get_valid_stinking_cloud_pos, (int, int));
@@ -711,183 +706,13 @@ int curse_bless;
}
}
/* Forget known information about this object type. */
static void
forget_single_object(obj_id)
int obj_id;
{
objects[obj_id].oc_name_known = 0;
objects[obj_id].oc_pre_discovered = 0; /* a discovery when relearned */
if (objects[obj_id].oc_uname) {
free((genericptr_t) objects[obj_id].oc_uname);
objects[obj_id].oc_uname = 0;
}
undiscover_object(obj_id); /* after clearing oc_name_known */
/* clear & free object names from matching inventory items too? */
}
#if 0 /* here if anyone wants it.... */
/* Forget everything known about a particular object class. */
static void
forget_objclass(oclass)
int oclass;
{
int i;
for (i = g.bases[oclass];
i < NUM_OBJECTS && objects[i].oc_class == oclass; i++)
forget_single_object(i);
}
#endif
/* randomize the given list of numbers 0 <= i < count */
static void
randomize(indices, count)
int *indices;
int count;
{
int i, iswap, temp;
for (i = count - 1; i > 0; i--) {
if ((iswap = rn2(i + 1)) == i)
continue;
temp = indices[i];
indices[i] = indices[iswap];
indices[iswap] = temp;
}
}
/* Forget % of known objects. */
void
forget_objects(percent)
int percent;
{
int i, count;
int indices[NUM_OBJECTS];
if (percent == 0)
return;
if (percent <= 0 || percent > 100) {
impossible("forget_objects: bad percent %d", percent);
return;
}
indices[0] = 0; /* lint suppression */
for (count = 0, i = 1; i < NUM_OBJECTS; i++)
if (OBJ_DESCR(objects[i])
&& (objects[i].oc_name_known || objects[i].oc_uname))
indices[count++] = i;
if (count > 0) {
randomize(indices, count);
/* forget first % of randomized indices */
count = ((count * percent) + rn2(100)) / 100;
for (i = 0; i < count; i++)
forget_single_object(indices[i]);
}
}
/* Forget some or all of map (depends on parameters). */
void
forget_map(howmuch)
int howmuch;
{
register int zx, zy;
if (Sokoban)
return;
g.known = TRUE;
for (zx = 0; zx < COLNO; zx++)
for (zy = 0; zy < ROWNO; zy++)
if (howmuch & ALL_MAP || rn2(7)) {
/* Zonk all memory of this location. */
levl[zx][zy].seenv = 0;
levl[zx][zy].waslit = 0;
levl[zx][zy].glyph = GLYPH_UNEXPLORED;
g.lastseentyp[zx][zy] = STONE;
}
/* forget overview data for this level */
forget_mapseen(ledger_no(&u.uz));
}
/* Forget all traps on the level. */
void
forget_traps()
{
register struct trap *trap;
/* forget all traps (except the one the hero is in :-) */
for (trap = g.ftrap; trap; trap = trap->ntrap)
if ((trap->tx != u.ux || trap->ty != u.uy) && (trap->ttyp != HOLE))
trap->tseen = 0;
}
/*
* Forget given % of all levels that the hero has visited and not forgotten,
* except this one.
*/
void
forget_levels(percent)
int percent;
{
int i, count;
xchar maxl, this_lev;
int indices[MAXLINFO];
if (percent == 0)
return;
if (percent <= 0 || percent > 100) {
impossible("forget_levels: bad percent %d", percent);
return;
}
this_lev = ledger_no(&u.uz);
maxl = maxledgerno();
/* count & save indices of non-forgotten visited levels */
/* Sokoban levels are pre-mapped for the player, and should stay
* so, or they become nearly impossible to solve. But try to
* shift the forgetting elsewhere by fiddling with percent
* instead of forgetting fewer levels.
*/
indices[0] = 0; /* lint suppression */
for (count = 0, i = 0; i <= maxl; i++)
if ((g.level_info[i].flags & VISITED)
&& !(g.level_info[i].flags & FORGOTTEN) && i != this_lev) {
if (ledger_to_dnum(i) == sokoban_dnum)
percent += 2;
else
indices[count++] = i;
}
if (percent > 100)
percent = 100;
if (count > 0) {
randomize(indices, count);
/* forget first % of randomized indices */
count = ((count * percent) + 50) / 100;
for (i = 0; i < count; i++) {
g.level_info[indices[i]].flags |= FORGOTTEN;
forget_mapseen(indices[i]);
}
}
}
/*
* Forget some things (e.g. after reading a scroll of amnesia). When called,
* the following are always forgotten:
* - felt ball & chain
* - traps
* - part (6 out of 7) of the map
* - skill training
*
* Other things are subject to flags:
* howmuch & ALL_MAP = forget whole map
* howmuch & ALL_SPELLS = forget all spells
*/
static void
@@ -897,30 +722,11 @@ int howmuch;
if (Punished)
u.bc_felt = 0; /* forget felt ball&chain */
forget_map(howmuch);
forget_traps();
/* 1 in 3 chance of forgetting some levels */
if (!rn2(3))
forget_levels(rn2(25));
/* 1 in 3 chance of forgetting some objects */
if (!rn2(3))
forget_objects(rn2(25));
if (howmuch & ALL_SPELLS)
losespells();
/*
* Make sure that what was seen is restored correctly. To do this,
* we need to go blind for an instant --- turn off the display,
* then restart it. All this work is needed to correctly handle
* walls which are stone on one side and wall on the other. Turning
* off the seen bits above will make the wall revert to stone, but
* there are cases where we don't want this to happen. The easiest
* thing to do is to run it through the vision system again, which
* is always correct.
*/
docrt(); /* this correctly will reset vision */
/* Forget some skills. */
drain_weapon_skill(rnd(howmuch ? 5 : 3));
}
/* monster is hit by scroll of taming's effect */
@@ -1579,8 +1385,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
break;
case SCR_AMNESIA:
g.known = TRUE;
forget((!sblessed ? ALL_SPELLS : 0)
| (!confused || scursed ? ALL_MAP : 0));
forget((!sblessed ? ALL_SPELLS : 0));
if (Hallucination) /* Ommmmmm! */
Your("mind releases itself from mundane concerns.");
else if (!strncmpi(g.plname, "Maud", 4))
+1 -1
View File
@@ -210,7 +210,7 @@ dosit()
/* Magical voice not affected by deafness */
pline("A voice echoes:");
verbalize("Thy audience hath been summoned, %s!",
verbalize("Thine audience hath been summoned, %s!",
flags.female ? "Dame" : "Sire");
while (cnt--)
(void) makemon(courtmon(), u.ux, u.uy, NO_MM_FLAGS);
+2 -2
View File
@@ -453,8 +453,8 @@ boolean extras;
/* get_level_extends() returns -1,-1 to COLNO,ROWNO at max */
if (miny < 0)
miny = 0;
if (minx < 0)
minx = 0;
if (minx < 1)
minx = 1;
if (maxx >= COLNO)
maxx = (COLNO - 1);
if (maxy >= ROWNO)
-2
View File
@@ -397,8 +397,6 @@ learn(VOID_ARGS)
book->spestudied++;
exercise(A_WIS, TRUE); /* extra study */
}
/* make book become known even when spell is already
known, in case amnesia made you forget the book */
makeknown((int) booktype);
} else { /* (spellid(i) == NO_SPELL) */
/* for a normal book, spestudied will be zero, but for
+1 -5
View File
@@ -719,11 +719,7 @@ boolean break_the_rules; /* True: wizard mode ^T */
if (!Teleportation || (u.ulevel < (Role_if(PM_WIZARD) ? 8 : 12)
&& !can_teleport(g.youmonst.data))) {
/* Try to use teleport away spell.
Prior to 3.6.2 this used to require that you know the spellbook
(probably just intended as an optimization to skip the
lookup loop) but it is possible to know and cast a spell
after forgetting its book due to amnesia. */
/* Try to use teleport away spell. */
for (sp_no = 0; sp_no < MAXSPELL; sp_no++)
if (g.spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY)
break;
+3 -5
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1581886869 2020/02/16 21:01:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.227 $ */
/* NetHack 3.6 uhitm.c $NHDT-Date: 1584405117 2020/03/17 00:31:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.228 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -366,14 +366,12 @@ register struct monst *mtmp;
Strcpy(buf, y_monnam(mtmp));
buf[0] = highc(buf[0]);
You("stop. %s is in the way!", buf);
g.context.travel = g.context.travel1 = g.context.mv = g.context.run
= 0;
end_running(TRUE);
return TRUE;
} else if ((mtmp->mfrozen || (!mtmp->mcanmove)
|| (mtmp->data->mmove == 0)) && rn2(6)) {
pline("%s doesn't seem to move!", Monnam(mtmp));
g.context.travel = g.context.travel1 = g.context.mv = g.context.run
= 0;
end_running(TRUE);
return TRUE;
} else
return FALSE;
+38
View File
@@ -1373,6 +1373,44 @@ int n; /* number of slots to lose; normally one */
}
}
void
drain_weapon_skill(n)
int n; /* number of skills to drain */
{
int skill;
int i;
int tmpskills[P_NUM_SKILLS];
(void) memset((genericptr_t) tmpskills, 0, sizeof(tmpskills));
while (--n >= 0) {
if (u.skills_advanced) {
/* Pick a random skill, deleting it from the list. */
i = rn2(u.skills_advanced);
skill = u.skill_record[i];
tmpskills[skill] = 1;
for (; i < u.skills_advanced - 1; i++) {
u.skill_record[i] = u.skill_record[i + 1];
}
u.skills_advanced--;
if (P_SKILL(skill) <= P_UNSKILLED)
panic("drain_weapon_skill (%d)", skill);
P_SKILL(skill)--; /* drop skill one level */
/* refund slots used for skill */
u.weapon_slots += slots_required(skill);
/* drain a random proportion of skill training */
if (P_ADVANCE(skill))
P_ADVANCE(skill) = rn2(P_ADVANCE(skill));
}
}
for (skill = 0; skill < P_NUM_SKILLS; skill++)
if (tmpskills[skill]) {
You("forget %syour training in %s.",
P_SKILL(skill) >= P_BASIC ? "some of " : "", P_NAME(skill));
}
}
int
weapon_type(obj)
struct obj *obj;