]> granicus.if.org Git - nethack/commitdiff
Make free actions easier to predict, nonfree actions more predictable
authorAlex Smith <ais523@nethack4.org>
Sat, 12 Nov 2016 01:24:03 +0000 (01:24 +0000)
committerAlex Smith <ais523@nethack4.org>
Sat, 12 Nov 2016 01:24:03 +0000 (01:24 +0000)
This fixes melee kiting more comprehensively (it now doesn't work
against slower monsters either), and prevents you doing things like
opening up a gap when running from an imp (you couldn't do that in
3.4.3).

src/allmain.c
src/mon.c

index de1fb15577ebe33f6e98736ad2c39b868d488fe5..1ca917a74b367b80a29341311b5bca09e06d0c7a 100644 (file)
@@ -132,14 +132,13 @@ boolean resuming;
                         moveamt = youmonst.data->mmove;
 
                         if (Very_fast) { /* speed boots or potion */
-                            /* average movement is 1.67 times normal */
-                            moveamt += NORMAL_SPEED / 2;
-                            if (rn2(3) == 0)
-                                moveamt += NORMAL_SPEED / 2;
-                        } else if (Fast) {
-                            /* average movement is 1.33 times normal */
+                            /* gain a free action on 2/3 of turns */
                             if (rn2(3) != 0)
-                                moveamt += NORMAL_SPEED / 2;
+                                moveamt += NORMAL_SPEED;
+                        } else if (Fast) {
+                            /* gain a free action on 1/3 of turns */
+                            if (rn2(3) == 0)
+                                moveamt += NORMAL_SPEED;
                         }
                     }
 
index 35966e381b4d0c424251af038046c55f1bdc0c3f..f387655e786a92c40f7ca973d0504d514c4b344a 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -582,6 +582,7 @@ mcalcmove(mon)
 struct monst *mon;
 {
     int mmove = mon->data->mmove;
+    int mmove_adj;
 
     /* Note: MSLOW's `+ 1' prevents slowed speed 1 getting reduced to 0;
      *       MFAST's `+ 2' prevents hasted speed 1 from becoming a no-op;
@@ -592,20 +593,23 @@ struct monst *mon;
     else if (mon->mspeed == MFAST)
         mmove = (4 * mmove + 2) / 3;
 
-    if (mon == u.usteed) {
-        if (u.ugallop && context.mv) {
-            /* average movement is 1.50 times normal */
-            mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
-        }
-    } else if (mmove) {
-        /* vary movement points allocated to slightly reduce predictability;
-           random increment (avg +2) exceeds random decrement (avg +1) by
-           a small amount; normal speed monsters will occasionally get an
-           extra move and slow ones won't be quite as slow */
-        mmove += rn2(5) - rn2(3); /* + 0..4 - 0..2, average net +1 */
-        if (mmove < 1)
-            mmove = 1;
-    }
+    if (mon == u.usteed && u.ugallop && context.mv) {
+        /* increase movement by a factor of 1.5; also increase variance of
+           movement speed (if it's naturally 24, we don't want it to always
+           become 36) */
+        mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
+    }
+
+    /* Randomly round the monster's speed to a multiple of NORMAL_SPEED. This
+       makes it impossible for the player to predict when they'll get a free
+       turn (thus preventing exploits like "melee kiting"), while retaining
+       guarantees about shopkeepers not being outsped by a normal-speed player,
+       normal-speed players being unable to open up a gap when fleeing a
+       normal-speed monster, etc.*/
+    mmove_adj = mmove % NORMAL_SPEED;
+    mmove -= mmove_adj;
+    if (rn2(NORMAL_SPEED) < mmove_adj)
+        mmove += NORMAL_SPEED;
 
     return mmove;
 }