From: Pasi Kallinen Date: Wed, 1 Feb 2023 12:37:12 +0000 (+0200) Subject: Split monster looking for items into separate function X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=df8a0ac6546e38ab53654fb1432fcba080e4fbee;p=nethack Split monster looking for items into separate function --- diff --git a/src/monmove.c b/src/monmove.c index cdc20c83d..65a9121d6 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -16,6 +16,7 @@ static void mind_blast(struct monst *); static boolean holds_up_web(coordxy, coordxy); static int count_webbing_walls(coordxy, coordxy); static boolean soko_allow_web(struct monst *); +static boolean m_search_items(struct monst *, coordxy *, coordxy *, schar *, int *); static boolean leppie_avoidance(struct monst *); static void leppie_stash(struct monst *); static boolean m_balks_at_approaching(struct monst *); @@ -1095,6 +1096,110 @@ maybe_spin_web(struct monst *mtmp) } } +#define SQSRCHRADIUS 5 + +static boolean +m_search_items(struct monst *mtmp, coordxy *ggx, coordxy *ggy, schar *mmoved, int *appr) +{ + register int minr = SQSRCHRADIUS; /* not too far away */ + register struct obj *otmp; + register coordxy xx, yy; + coordxy oomx, oomy, lmx, lmy; + struct trap *ttmp; + coordxy omx = mtmp->mx, omy = mtmp->my; + struct permonst *ptr = mtmp->data; + struct monst *mtoo; + + /* cut down the search radius if it thinks character is closer. */ + if (distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS + && !mtmp->mpeaceful) + minr--; + /* guards shouldn't get too distracted */ + if (!mtmp->mpeaceful && is_mercenary(ptr)) + minr = 1; + + if ((!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) { + oomx = min(COLNO - 1, omx + minr); + oomy = min(ROWNO - 1, omy + minr); + lmx = max(1, omx - minr); + lmy = max(0, omy - minr); + for (otmp = fobj; otmp; otmp = otmp->nobj) { + /* monsters may pick rocks up, but won't go out of their way + to grab them; this might hamper sling wielders, but it cuts + down on move overhead by filtering out most common item */ + if (otmp->otyp == ROCK) + continue; + /* avoid special items; once hero picks them up, they'll + cease being special */ + if (is_mines_prize(otmp) || is_soko_prize(otmp)) + continue; + + xx = otmp->ox; + yy = otmp->oy; + /* Nymphs take everything. Most other creatures should not + * pick up corpses except as a special case like in + * searches_for_item(). We need to do this check in + * mpickstuff() as well. + */ + if (xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) { + /* don't get stuck circling around object that's + underneath an immobile or hidden monster; + paralysis victims excluded */ + if ((mtoo = m_at(xx, yy)) != 0 + && (helpless(mtoo) || mtoo->mundetected + || (mtoo->mappearance && !mtoo->iswiz) + || !mtoo->data->mmove)) + continue; + /* the mfndpos() test for whether to allow a move to a + water location accepts flyers, but they can't reach + underwater objects, so being able to move to a spot + is insufficient for deciding whether to do so */ + if (!could_reach_item(mtmp, xx, yy)) + continue; + + /* ignore obj if there's a trap and monster knows it */ + if ((ttmp = t_at(xx, yy)) != 0 + && mon_knows_traps(mtmp, ttmp->ttyp)) { + if (*ggx == xx && *ggy == yy) { + *ggx = mtmp->mux; + *ggy = mtmp->muy; + } + continue; + } + + if (((mon_would_take_item(mtmp, otmp) && (can_carry(mtmp, otmp) > 0)) + || (hides_under(ptr) && !cansee(otmp->ox, otmp->oy))) + && can_touch_safely(mtmp, otmp) + /* Don't get stuck circling an Elbereth */ + && !onscary(xx, yy, mtmp)) { + minr = distmin(omx, omy, xx, yy); + oomx = min(COLNO - 1, omx + minr); + oomy = min(ROWNO - 1, omy + minr); + lmx = max(1, omx - minr); + lmy = max(0, omy - minr); + *ggx = otmp->ox; + *ggy = otmp->oy; + if (*ggx == omx && *ggy == omy) { + *mmoved = MMOVE_DONE; /* actually unnecessary */ + return TRUE; + } + } + } + } + } + + if (minr < SQSRCHRADIUS && *appr == -1) { + if (distmin(omx, omy, mtmp->mux, mtmp->muy) <= 3) { + *ggx = mtmp->mux; + *ggy = mtmp->muy; + } else + *appr = 1; + } + return FALSE; +} + +#undef SQSRCHRADIUS + /* Handles the movement of a standard monster. */ /* Return values: * 0: did not move, but can still attack and do other stuff. @@ -1116,7 +1221,6 @@ m_move(register struct monst* mtmp, register int after) boolean better_with_displacing = FALSE; boolean sawmon = canspotmon(mtmp); /* before it moved */ struct permonst *ptr; - struct monst *mtoo; schar mmoved = MMOVE_NOTHING; /* not strictly nec.: chi >= 0 will do */ long info[9]; long flag; @@ -1280,101 +1384,8 @@ m_move(register struct monst* mtmp, register int after) } } -#define SQSRCHRADIUS 5 - - if (getitems) { - register int minr = SQSRCHRADIUS; /* not too far away */ - register struct obj *otmp; - register coordxy xx, yy; - coordxy oomx, oomy, lmx, lmy; - struct trap *ttmp; - - /* cut down the search radius if it thinks character is closer. */ - if (distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS - && !mtmp->mpeaceful) - minr--; - /* guards shouldn't get too distracted */ - if (!mtmp->mpeaceful && is_mercenary(ptr)) - minr = 1; - - if ((!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) { - oomx = min(COLNO - 1, omx + minr); - oomy = min(ROWNO - 1, omy + minr); - lmx = max(1, omx - minr); - lmy = max(0, omy - minr); - for (otmp = fobj; otmp; otmp = otmp->nobj) { - /* monsters may pick rocks up, but won't go out of their way - to grab them; this might hamper sling wielders, but it cuts - down on move overhead by filtering out most common item */ - if (otmp->otyp == ROCK) - continue; - /* avoid special items; once hero picks them up, they'll - cease being special */ - if (is_mines_prize(otmp) || is_soko_prize(otmp)) - continue; - - xx = otmp->ox; - yy = otmp->oy; - /* Nymphs take everything. Most other creatures should not - * pick up corpses except as a special case like in - * searches_for_item(). We need to do this check in - * mpickstuff() as well. - */ - if (xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) { - /* don't get stuck circling around object that's - underneath an immobile or hidden monster; - paralysis victims excluded */ - if ((mtoo = m_at(xx, yy)) != 0 - && (helpless(mtoo) || mtoo->mundetected - || (mtoo->mappearance && !mtoo->iswiz) - || !mtoo->data->mmove)) - continue; - /* the mfndpos() test for whether to allow a move to a - water location accepts flyers, but they can't reach - underwater objects, so being able to move to a spot - is insufficient for deciding whether to do so */ - if (!could_reach_item(mtmp, xx, yy)) - continue; - - /* ignore obj if there's a trap and monster knows it */ - if ((ttmp = t_at(xx, yy)) != 0 - && mon_knows_traps(mtmp, ttmp->ttyp)) { - if (ggx == xx && ggy == yy) { - ggx = mtmp->mux; - ggy = mtmp->muy; - } - continue; - } - - if (((mon_would_take_item(mtmp, otmp) && (can_carry(mtmp, otmp) > 0)) - || (hides_under(ptr) && !cansee(otmp->ox, otmp->oy))) - && can_touch_safely(mtmp, otmp) - /* Don't get stuck circling an Elbereth */ - && !onscary(xx, yy, mtmp)) { - minr = distmin(omx, omy, xx, yy); - oomx = min(COLNO - 1, omx + minr); - oomy = min(ROWNO - 1, omy + minr); - lmx = max(1, omx - minr); - lmy = max(0, omy - minr); - ggx = otmp->ox; - ggy = otmp->oy; - if (ggx == omx && ggy == omy) { - mmoved = MMOVE_DONE; /* actually unnecessary */ - goto postmov; - } - } - } - } - } - - if (minr < SQSRCHRADIUS && appr == -1) { - if (distmin(omx, omy, mtmp->mux, mtmp->muy) <= 3) { - ggx = mtmp->mux; - ggy = mtmp->muy; - } else - appr = 1; - } - } + if (getitems && m_search_items(mtmp, &ggx, &ggy, &mmoved, &appr)) + goto postmov; /* don't tunnel if hostile and close enough to prefer a weapon */ if (can_tunnel && needspick(ptr)