From 57abae29e8721a2bdf3d280faffe7b8615d311c0 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Sun, 8 Dec 2024 22:18:27 +0200 Subject: [PATCH] Don't switch away from polearm if monster in range Using 'f', if hero is wielding a polearm, and a monster is in range, don't switch away even if we do have ammo in quiver and a launcher in the inventory. --- include/extern.h | 1 + src/apply.c | 89 +++++++++++++++++++++++++++++++++--------------- src/dothrow.c | 2 ++ 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/include/extern.h b/include/extern.h index 6aaec4e26..9b596197a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -126,6 +126,7 @@ extern void use_unicorn_horn(struct obj **); extern boolean tinnable(struct obj *) NONNULLPTRS; extern void reset_trapset(void); extern int use_whip(struct obj *) NONNULLPTRS; +extern boolean could_pole_mon(void); extern int use_pole(struct obj *, boolean) NONNULLPTRS; extern void fig_transform(union any *, long) NONNULLARG1; extern int unfixable_trouble_count(boolean); diff --git a/src/apply.c b/src/apply.c index c585afa7e..7e4c85c1c 100644 --- a/src/apply.c +++ b/src/apply.c @@ -32,6 +32,7 @@ staticfn int touchstone_ok(struct obj *); staticfn int use_stone(struct obj *); staticfn int set_trap(void); /* occupation callback */ staticfn void display_polearm_positions(boolean); +staticfn void calc_pole_range(int *, int *); staticfn int use_cream_pie(struct obj *); staticfn int jelly_ok(struct obj *); staticfn int use_royal_jelly(struct obj **); @@ -3341,12 +3342,71 @@ display_polearm_positions(boolean on_off) } } +/* + * Calculate allowable range (pole's reach is always 2 steps): + * unskilled and basic: orthogonal direction, 4..4; + * skilled: as basic, plus knight's jump position, 4..5; + * expert: as skilled, plus diagonal, 4..8. + * ...9... + * .85458. + * .52125. + * 9410149 + * .52125. + * .85458. + * ...9... + * (Note: no roles in NetHack can become expert or better + * for polearm skill; Yeoman in slash'em can become expert.) + */ +staticfn void +calc_pole_range(int *min_range, int *max_range) +{ + int typ = uwep_skill_type(); + + *min_range = 4; + if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) + *max_range = 4; + else if (P_SKILL(typ) == P_SKILLED) + *max_range = 5; + else + *max_range = 8; /* (P_SKILL(typ) >= P_EXPERT) */ + + gp.polearm_range_min = *min_range; + gp.polearm_range_max = *max_range; + +} + +/* return TRUE if hero is wielding a polearm and there's + at least one monster they could hit with it */ +boolean +could_pole_mon(void) +{ + int min_range, max_range; + coord cc; + struct monst *hitm = svc.context.polearm.hitmon; + + if (!uwep || !is_pole(uwep)) + return FALSE; + + calc_pole_range(&min_range, &max_range); + + cc.x = u.ux; + cc.y = u.uy; + if (!find_poleable_mon(&cc, min_range, max_range)) { + if (hitm && !DEADMONSTER(hitm) && sensemon(hitm) + && mdistu(hitm) <= max_range && mdistu(hitm) >= min_range) + return TRUE; + } else { + return TRUE; + } + return FALSE; +} + /* Distance attacks by pole-weapons */ int use_pole(struct obj *obj, boolean autohit) { const char thump[] = "Thump! Your blow bounces harmlessly off the %s."; - int res = ECMD_OK, typ, max_range, min_range, glyph; + int res = ECMD_OK, max_range, min_range, glyph; coord cc; struct monst *mtmp; struct monst *hitm = svc.context.polearm.hitmon; @@ -3366,32 +3426,7 @@ use_pole(struct obj *obj, boolean autohit) } /* assert(obj == uwep); */ - /* - * Calculate allowable range (pole's reach is always 2 steps): - * unskilled and basic: orthogonal direction, 4..4; - * skilled: as basic, plus knight's jump position, 4..5; - * expert: as skilled, plus diagonal, 4..8. - * ...9... - * .85458. - * .52125. - * 9410149 - * .52125. - * .85458. - * ...9... - * (Note: no roles in NetHack can become expert or better - * for polearm skill; Yeoman in slash'em can become expert.) - */ - min_range = 4; - typ = uwep_skill_type(); - if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) - max_range = 4; - else if (P_SKILL(typ) == P_SKILLED) - max_range = 5; - else - max_range = 8; /* (P_SKILL(typ) >= P_EXPERT) */ - - gp.polearm_range_min = min_range; - gp.polearm_range_max = max_range; + calc_pole_range(&min_range, &max_range); /* Prompt for a location */ if (!autohit) diff --git a/src/dothrow.c b/src/dothrow.c index 7dcf043f9..5ce3570a2 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -553,6 +553,8 @@ dofire(void) if (uquiver && is_ammo(uquiver) && iflags.fireassist) { struct obj *olauncher; + if (uwep && is_pole(uwep) && could_pole_mon()) + return use_pole(uwep, TRUE); /* Try to find a launcher */ if (ammo_and_launcher(uquiver, uwep)) { obj = uquiver;