]> granicus.if.org Git - nethack/commitdiff
Split pet ranged attack into separate function
authorPasi Kallinen <paxed@alt.org>
Wed, 25 Jan 2023 09:27:14 +0000 (11:27 +0200)
committerPasi Kallinen <paxed@alt.org>
Wed, 25 Jan 2023 09:27:14 +0000 (11:27 +0200)
src/dogmove.c

index 3833ee62655ea328df6d085294196d48d47ad273..ce4ab4a737ad61314e6fa469d67322d0725b3607 100644 (file)
@@ -18,6 +18,7 @@ static int dog_goal(struct monst *, struct edog *, int, int, int);
 static struct monst *find_targ(struct monst *, int, int, int);
 static int find_friends(struct monst *, struct monst *, int);
 static struct monst *best_target(struct monst *);
+static int pet_ranged_attk(struct monst *);
 static long score_targ(struct monst *, struct monst *);
 static boolean can_reach_location(struct monst *, coordxy, coordxy, coordxy,
                                   coordxy);
@@ -854,6 +855,81 @@ best_target(struct monst *mtmp)   /* Pet */
     return best_targ;
 }
 
+/* Pet considers and maybe executes a ranged attack */
+static int
+pet_ranged_attk(struct monst *mtmp)
+{
+    struct monst *mtarg;
+    int hungry = 0;
+
+    /* How hungry is the pet? */
+    if (!mtmp->isminion) {
+        struct edog *dog = EDOG(mtmp);
+
+        hungry = (gm.moves > (dog->hungrytime + DOG_HUNGRY));
+    }
+
+    /* Identify the best target in a straight line from the pet;
+     * if there is such a target, we'll let the pet attempt an attack.
+     */
+    mtarg = best_target(mtmp);
+
+    /* Hungry pets are unlikely to use breath/spit attacks */
+    if (mtarg && (!hungry || !rn2(5))) {
+        int mstatus = MM_MISS;
+
+        if (mtarg == &gy.youmonst) {
+            if (mattacku(mtmp))
+                return MMOVE_DIED;
+            /* Treat this as the pet having initiated an attack even if it
+             * didn't, so it will lose its move.  This isn't entirely fair,
+             * but mattacku doesn't distinguish between "did not attack"
+             * and "attacked but didn't die" cases, and this is preferable
+             * to letting the pet attack the player and continuing to move.
+             */
+            mstatus = MM_HIT;
+        } else {
+            mstatus = mattackm(mtmp, mtarg);
+
+            /* Shouldn't happen, really */
+            if (mstatus & MM_AGR_DIED)
+                return MMOVE_DIED;
+
+            /* Allow the targeted nasty to strike back - if
+             * the targeted beast doesn't have a ranged attack,
+             * nothing will happen.
+             */
+            if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
+                && rn2(4) && mtarg != &gy.youmonst) {
+
+                /* Can monster see?  If it can, it can retaliate
+                 * even if the pet is invisible, since it'll see
+                 * the direction from which the ranged attack came;
+                 * if it's blind or unseeing, it can't retaliate
+                 */
+                if (mtarg->mcansee && haseyes(mtarg->data)) {
+                    mstatus = mattackm(mtarg, mtmp);
+                    if (mstatus & MM_DEF_DIED)
+                        return MMOVE_DIED;
+                }
+            }
+        }
+        /* Only return 3 if the pet actually made a ranged attack, and
+         * thus should lose the rest of its move.
+         * There's a chain of assumptions here:
+         * 1. score_targ and best_target will never select a monster
+         *    that can be attacked in melee, so the mattackm call can
+         *    only ever try ranged options
+         * 2. if the only attacks available to mattackm are ranged
+         *    options, and the monster cannot make a ranged attack, it
+         *    will return MM_MISS.
+         */
+        if (mstatus != MM_MISS)
+            return MMOVE_DONE;
+    }
+    return MMOVE_NOTHING;
+}
+
 /* Return values (same as m_move):
  * 0: did not move, but can still attack and do other stuff.
  * 1: moved, possibly can attack.
@@ -1130,76 +1206,8 @@ dog_move(register struct monst *mtmp,
      * now's the time for ranged attacks. Note that the pet can move
      * after it performs its ranged attack. Should this be changed?
      */
-    {
-        struct monst *mtarg;
-        int hungry = 0;
-
-        /* How hungry is the pet? */
-        if (!mtmp->isminion) {
-            struct edog *dog = EDOG(mtmp);
-
-            hungry = (gm.moves > (dog->hungrytime + DOG_HUNGRY));
-        }
-
-        /* Identify the best target in a straight line from the pet;
-         * if there is such a target, we'll let the pet attempt an attack.
-         */
-        mtarg = best_target(mtmp);
-
-        /* Hungry pets are unlikely to use breath/spit attacks */
-        if (mtarg && (!hungry || !rn2(5))) {
-            int mstatus = MM_MISS;
-
-            if (mtarg == &gy.youmonst) {
-                if (mattacku(mtmp))
-                    return MMOVE_DIED;
-                /* Treat this as the pet having initiated an attack even if it
-                 * didn't, so it will lose its move.  This isn't entirely fair,
-                 * but mattacku doesn't distinguish between "did not attack"
-                 * and "attacked but didn't die" cases, and this is preferable
-                 * to letting the pet attack the player and continuing to move.
-                 */
-                mstatus = MM_HIT;
-            } else {
-                mstatus = mattackm(mtmp, mtarg);
-
-                /* Shouldn't happen, really */
-                if (mstatus & MM_AGR_DIED)
-                    return MMOVE_DIED;
-
-                /* Allow the targeted nasty to strike back - if
-                 * the targeted beast doesn't have a ranged attack,
-                 * nothing will happen.
-                 */
-                if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
-                    && rn2(4) && mtarg != &gy.youmonst) {
-
-                    /* Can monster see?  If it can, it can retaliate
-                     * even if the pet is invisible, since it'll see
-                     * the direction from which the ranged attack came;
-                     * if it's blind or unseeing, it can't retaliate
-                     */
-                    if (mtarg->mcansee && haseyes(mtarg->data)) {
-                        mstatus = mattackm(mtarg, mtmp);
-                        if (mstatus & MM_DEF_DIED)
-                            return MMOVE_DIED;
-                    }
-                }
-            }
-            /* Only return 3 if the pet actually made a ranged attack, and
-             * thus should lose the rest of its move.
-             * There's a chain of assumptions here:
-             * 1. score_targ and best_target will never select a monster
-             *    that can be attacked in melee, so the mattackm call can
-             *    only ever try ranged options
-             * 2. if the only attacks available to mattackm are ranged
-             *    options, and the monster cannot make a ranged attack, it
-             *    will return MM_MISS.
-             */
-            if (mstatus != MM_MISS)
-                return MMOVE_DONE;
-        }
-    }
+    if ((i = pet_ranged_attk(mtmp)) != MMOVE_NOTHING)
+        return i;
 
  newdogpos:
     if (nix != omx || niy != omy) {