I wanted to make mob movements a little more unique - after all, we can select their attack text so why not their movements in and out of a room? Join me on a clumsy journey through C and make your mud a little cooler with customized mob movement.
All of this is AFTER I added my "minimum level to kill" snippet (good luck finding it in the forums, I added it in a trigger request) so some of the integers/variables (especially loading/saving for mobs) might have more functions/variables than stock TBA.
Let's begin.
In structs.h add
Code:
/* Mob Movement */
#define MOB_WALKS      1
#define MOB_SKIPS      2
#define MOB_STAGGERS   3
#define MOB_SWIMS      4
#define MOB_SLINKS     5
#define MOB_SAUNTERS   6
#define MOB_STRUTS     7
#define MOB_LIMPS      8
#define MOB_MEANDERS   9
#define MOB_SHUFFLES   10
#define MOB_RUNS       11
#define MOB_ROLLS      12
#define MOB_MARCHES    13
#define NUM_MOB_MOVEMENT 14
 
This is where you can add more/change the type of movement....
AND added in /** Special data used by NPCs, not PCs */
In utils.h add:
Code:
#define GET_MOBMOVE(ch)      ((ch)->mob_specials.mobmove)
 
In oasis.h add:
Code:
#define MEDIT_MOVEMENT              41
 
this number might be different for you, just do the next avail number.
In  act.movement.c add (I added this above the functions):
Code:
/* movement text for mobs */
const char *mob_movement_text[] =
{
  "walks",
  "skips",
  "staggers",
  "swims",
  "slinks",
  "saunters",
  "struts",
  "limps",
  "meanders",
  "shuffles",
  "skips",
  "runs",
  "rolls",
  "marches"
};
 
Since we're here I decided to change the arrival messages as well:
Change    /* Generate the leave message and display to others in the was_in room. */ to give a movement message w a direction if it's a character OR our modified message if it's a NPC:
Code:
/* Generate the leave message and display to others in the was_in room. */
  if (!IS_NPC(ch)) {
    if (!AFF_FLAGGED(ch, AFF_SNEAK)) {
    snprintf(leave_message, sizeof(leave_message), "$n leaves %s.", dirs[dir]);
    act(leave_message, TRUE, ch, 0, 0, TO_ROOM);
    }
  }
  else
  {
    snprintf(leave_message, sizeof(leave_message), "$n %s %s.", mob_movement_text[(int)GET_MOBMOVE(ch)], dirs[dir]);
    act(leave_message, TRUE, ch, 0, 0, TO_ROOM);
  }
 
under Local variable definitions add:
Code:
char arrive_message{SMALL_BUFSIZE];
 
then change the if in  /* Display arrival information to anyone in the destination room... */ to:
(cleaned this up to be a fancy conditional operator I found in a snippet way after I wrote this and it has 3 variables? that even legal? I don't care, it works)
Code:
  /* Display arrival information to anyone in the destination room... */
  if (!IS_NPC(ch)) {
    if (!AFF_FLAGGED(ch, AFF_SNEAK)) {
    snprintf(arrive_message, sizeof(arrive_message), "$n arrives from %s%s.",
    ((dir == 4 || dir == 5) ? "" : "the "),
    (dir == 4 ? "below": dir == 5 ? "above" : dirs[rev_dir[dir]]));
    act(arrive_message, TRUE, ch, 0, 0, TO_ROOM);
    }
  } else {
    snprintf(arrive_message, sizeof(arrive_message), "$n %s in from %s%s.", mob_movement_text[(int)GET_MOBMOVE(ch)],
    ((dir == 4 || dir == 5) ? "" : "the "),
    (dir == 4 ? "below": dir == 5 ? "above" : dirs[rev_dir[dir]]));
    act(arrive_message, TRUE, ch, 0, 0, TO_ROOM);
  }
 
In act.h under /* Global variables from act.movement.c */ add:
Code:
extern const char *mob_movement_text[];
 
Over to medit.c so we can select the movement for each mob:
add in to the includes:
in local functions add:
Code:
static void medit_disp_movement_types(struct descriptor_data *d);
 
then add the movement text menu option:
Code:
sprintbitarray(AFF_FLAGS(mob), affected_bits, AF_ARRAY_MAX, flag2);
  write_to_output(d,
          "%s6%s) Position  : %s%s\r\n"
          "%s7%s) Default  : %s%s\r\n"
          "%s8%s) Attack    : %s%s\r\n"
          "%sV%s) Move Text : %s%s\r\n"
          "%s9%s) Stats Menu...\r\n"
          "%sA%s) NPC Flags : %s%s\r\n"
          "%sB%s) AFF Flags : %s%s\r\n"
          "%sS%s) Script    : %s%s\r\n"
          "%sW%s) Copy mob\r\n"
          "%sX%s) Delete mob\r\n"
          "%sQ%s) Quit\r\n"
          "Enter choice : ",
          grn, nrm, yel, position_types[(int)GET_POS(mob)],
          grn, nrm, yel, position_types[(int)GET_DEFAULT_POS(mob)],
          grn, nrm, yel, attack_hit_text[(int)GET_ATTACK(mob)].singular,
          grn, nrm, yel, mob_movement_text[(int)GET_MOBMOVE(mob)],
          grn, nrm,
          grn, nrm, cyn, flags,
          grn, nrm, cyn, flag2,
          grn, nrm, cyn, OLC_SCRIPT(d) ?"Set.":"Not Set.",
          grn, nrm,
          grn, nrm,
          grn, nrm
          );
 
Then in case MEDIT_MAIN_MENU add:
Code:
    case 'V': // right? V for movement?
    case 'v': // Zi rulez
      OLC_MODE(d) = MEDIT_MOVEMENT;
      medit_disp_movement_types(d);
      return;
 
And in the cases under /* Numerical responses. */ add:
Code:
  case MEDIT_MOVEMENT:
    GET_MOBMOVE(OLC_MOB(d)) = LIMIT(i, 0, NUM_MOB_MOVEMENT - 1);
    break;
 
under "Display attack types menu" add:
Code:
/* Display movement types menu. */
static void medit_disp_movement_types(struct descriptor_data *d)
{
  int i;
  get_char_colors(d->character);
  clear_screen(d);
  for (i = 0; i < NUM_MOB_MOVEMENT; i++) {
    write_to_output(d, "%s%2d%s) %s\r\n", grn, i, nrm, mob_movement_text[i]);
  }
  write_to_output(d, "Enter move type : ");
}
 
Now we turn to saving and loading for the mobs
In genmob.c replaced this in write_mobile_record - please note I'm using my minimum attack level snippet as well which is why I'm writing a little extra in the second line of integers.
Code:
  if(n < MAX_STRING_LENGTH) {
    fprintf(fd, "%s", convert_from_tabs(buf));
    fprintf(fd, "%d %d %d %d %d %d %d %d %d E\n"
        "%d %d %d %dd%d+%d %dd%d+%d %d %d\n",
        MOB_FLAGS(mob)[0], MOB_FLAGS(mob)[1],
        MOB_FLAGS(mob)[2], MOB_FLAGS(mob)[3],
        AFF_FLAGS(mob)[0], AFF_FLAGS(mob)[1],
        AFF_FLAGS(mob)[2], AFF_FLAGS(mob)[3],
        GET_ALIGNMENT(mob),
        GET_LEVEL(mob), 20 - GET_HITROLL(mob), GET_AC(mob) / 10, GET_HIT(mob),
        GET_MANA(mob), GET_MOVE(mob), GET_NDD(mob), GET_SDD(mob),
        GET_DAMROLL(mob),GET_ATKLEVEL(mob), GET_MOBMOVE(mob));
 
in db.c (loading mob) in parse_simple_mob increase the array to the appropriate size (I'm up to 11) at the start of the function. It looks like:
then change this line read to:
Code:
  if (sscanf(line, " %d %d %d %dd%d+%d %dd%d+%d %d %d",
          t, t + 1, t + 2, t + 3, t + 4, t + 5, t + 6, t + 7, t + 8, t + 9, t + 10) != 11) {
    log("SYSERR: Format error in mob #%d, first line after S flag\n"
        "...expecting line of form '# # # #d#+# #d#+# # #'", nr);
    exit(1);
  }
  GET_LEVEL(mob_proto + i) = t[0];
  GET_HITROLL(mob_proto + i) = 20 - t[1];
  GET_AC(mob_proto + i) = 10 * t[2];
  /* max hit = 0 is a flag that H, M, V is xdy+z */
  GET_MAX_HIT(mob_proto + i) = 0;
  GET_HIT(mob_proto + i) = t[3];
  GET_MANA(mob_proto + i) = t[4];
  GET_MOVE(mob_proto + i) = t[5];
  GET_MAX_MANA(mob_proto + i) = 10;
  GET_MAX_MOVE(mob_proto + i) = 50;
  mob_proto[i].mob_specials.damnodice = t[6];
  mob_proto[i].mob_specials.damsizedice = t[7];
  GET_DAMROLL(mob_proto + i) = t[8];
  GET_ATKLEVEL(mob_proto + i) = t[9]; //this is added from a previous snippet
  GET_MOBMOVE(mob_proto + i) = t[10]; //we're adding this
 
That SHOULD be it. Now when my cyborg mob enters the room the character sees "A Level 2 Training Cyborg rolls in from the west." and when it leaves they see "A Level 2 Training Cyborg rolls east." My mud is far more descriptive than that... this is for a training area so relax. 
BIG NOTE: You will have to go back and add a number (just do 1) to each mob, so if you have a fully developed mud or are using TBA stock you're in for wrist-breaking trouble. For me it was adding a number to each mob in the x.mob file:  # # # #d#+# #d#+# # # <
this is what I added. The # before our added number is for my minimum attack level (another snippet).
PLEASE let me know if you run into any problems implementing, or if there's a more efficient way to do this. With the effort added to make our mob attacks personalized, this felt like a natural progression. I'd love to see it added to a release, but it would mean changing mob files and who wants to do that?
EDIT: Added a little logic to handle characters arriving from above and below (directions 4 & 5). Now that I'm thinking about it one would have to extrapolate that out if your mud handles all 10 directions...