From 9f2ca001382c8c6225e08026c19f4c8257c48209 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Tue, 1 May 2012 02:22:33 +0000 Subject: [PATCH] fix [part of] #H2554 - hunger when declining to attack peaceful monst Reported last December by , attempting to move into a peaceful monster's position and then declining to attack at the confirmation prompt uses no time, as expected, but does burn nutrition the same as if you carried out the attack. A player could abuse that to make room to eat an intrinisic-conferring corpse before it rots away. This fixes that, and also makes attacking a monster via applying a polearm and via kicking burn the same extra nutrition as ordinary attack. I didn't add it for attacking via throwing. He/she also reported that kicking at a peaceful monster and declining to attack at the prompt wakes up nearby monsters even though no actual kick ultimately takes place. I can confirm that, but this does not fix it. --- doc/fixes35.0 | 2 ++ include/extern.h | 1 + src/apply.c | 1 + src/dokick.c | 8 ++++++++ src/hack.c | 36 ++++++++++++++++++++++-------------- src/uhitm.c | 16 ++++++++-------- 6 files changed, 42 insertions(+), 22 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 968fa79fd..5007eca1c 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -834,6 +834,8 @@ magic mapping now displays furniture in preference to known or remembered traps or objects and known traps in preference to remembered objects restrictions on diagonal movement were ignored when crawling out of water when using magic whistle, prevent steed from being affected (trap interaction) +declining to attack a peaceful monster burned nutrition even though no action + took place Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index bb279fd7f..0e7eb4420 100644 --- a/include/extern.h +++ b/include/extern.h @@ -802,6 +802,7 @@ E int FDECL(cant_squeeze_thru, (struct monst *)); E boolean FDECL(invocation_pos, (XCHAR_P,XCHAR_P)); E boolean FDECL(test_move, (int, int, int, int, int)); E void NDECL(domove); +E boolean NDECL(overexertion); E void NDECL(invocation_message); E boolean FDECL(pooleffects, (BOOLEAN_P)); E void FDECL(spoteffects, (BOOLEAN_P)); diff --git a/src/apply.c b/src/apply.c index 1b0c001a1..77608b38e 100644 --- a/src/apply.c +++ b/src/apply.c @@ -2649,6 +2649,7 @@ use_pole(obj) bhitpos = cc; if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != (struct monst *)0) { if (attack_checks(mtmp, uwep)) return res; + if (overexertion()) return 1; /* burn nutrition; maybe pass out */ check_caitiff(mtmp); notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my); (void) thitmonst(mtmp, uwep); diff --git a/src/dokick.c b/src/dokick.c index 0238c0c34..15d685bd8 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -125,6 +125,9 @@ register xchar x, y; bhitpos.x = x; bhitpos.y = y; if (attack_checks(mon, (struct obj *)0)) return; + /* burn extra nutrition, same as direct combat; + maybe pass out before making target angry */ + if (overexertion()) return; /* anger target even if wild miss will occur */ setmangry(mon); @@ -805,6 +808,11 @@ dokick() * ceiling shouldn't be kickable (unless hero is flying?); * kicking toward them should just target whatever is on * the floor at that spot.] + * [FIXME too: kick_monster() calls attack_checks() which gives + * the player a chance to decline to attack a peaceful monster, + * and also calls overexertion() so hero might pass out before + * performing the kick. We shouldn't call wake_nearby() (and + * u_wipe_engr(), both already done above) in such cases.] */ if(MON_AT(x, y)) { diff --git a/src/hack.c b/src/hack.c index 2899a9312..055930d9f 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1329,20 +1329,6 @@ domove() if(context.forcefight || !mtmp->mundetected || sensemon(mtmp) || ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) && !is_safepet(mtmp))){ - gethungry(); - if(wtcap >= HVY_ENCUMBER && moves%3) { - if (Upolyd && u.mh > 1) { - u.mh--; - } else if (!Upolyd && u.uhp > 1) { - u.uhp--; - } else { - You("pass out from exertion!"); - exercise(A_CON, FALSE); - fall_asleep(-10, FALSE); - } - } - if(multi < 0) return; /* we just fainted */ - /* try to attack; note that it might evade */ /* also, we don't attack tame when _safepet_ */ if(attack(mtmp)) return; @@ -1621,6 +1607,28 @@ domove() } } +/* combat increases metabolism */ +boolean +overexertion() +{ + /* this used to be part of domove() when moving to a monster's + position, but is now called by attack() so that it doesn't + execute if you decline to attack a peaceful monster */ + gethungry(); + if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) { + int *hp = (!Upolyd ? &u.uhp : &u.mh); + + if (*hp > 1) { + *hp -= 1; + } else { + You("pass out from exertion!"); + exercise(A_CON, FALSE); + fall_asleep(-10, FALSE); + } + } + return (multi < 0); /* might have fainted (actually gone to sleep) */ +} + void invocation_message() { diff --git a/src/uhitm.c b/src/uhitm.c index 568be33f8..cbd0cdbec 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -366,16 +366,16 @@ register struct monst *mtmp; bhitpos.y = u.uy + u.dy; if (attack_checks(mtmp, uwep)) return(TRUE); - if (Upolyd) { - /* certain "pacifist" monsters don't attack */ - if(noattacks(youmonst.data)) { - You("have no way to attack monsters physically."); - mtmp->mstrategy &= ~STRAT_WAITMASK; - goto atk_done; - } + if (Upolyd && noattacks(youmonst.data)) { + /* certain "pacifist" monsters don't attack */ + You("have no way to attack monsters physically."); + mtmp->mstrategy &= ~STRAT_WAITMASK; + goto atk_done; } - if(check_capacity("You cannot fight while so heavily loaded.")) + if (check_capacity("You cannot fight while so heavily loaded.") || + /* consume extra nutrition during combat; maybe pass out */ + overexertion()) goto atk_done; if (u.twoweap && !can_twoweapon()) -- 2.40.0