I fixed the ch references in ACMD(do_buck) so that the rider gets hurt when he
gets thrown off instead of the mount, and fixed a small bug which made the
"$n has arrived message" show up twice when they were riding.
					-- Mike Sulmicki of Axxenfall
					   (sulmicki.erols.com 4000)
diff -c stock_src/act.informative.c src/act.informative.c
*** stock_src/act.informative.c	Mon Dec 16 05:19:56 1996
--- src/act.informative.c	Mon Dec 16 09:13:44 1996
***************
*** 163,168 ****
--- 163,184 ----
      act("You see nothing special about $m.", FALSE, i, 0, ch, TO_VICT);
  
    diag_char_to_char(i, ch);
+   
+   if (RIDING(i) && RIDING(i)->in_room == i->in_room) {
+     if (RIDING(i) == ch)
+       act("$e is mounted on you.", FALSE, i, 0, ch, TO_VICT);
+     else {
+       sprintf(buf2, "$e is mounted upon %s.", PERS(RIDING(i), ch));
+       act(buf2, FALSE, i, 0, ch, TO_VICT);
+     }
+   } else if (RIDDEN_BY(i) && RIDDEN_BY(i)->in_room == i->in_room) {
+     if (RIDDEN_BY(i) == ch)
+       act("You are mounted upon $m.", FALSE, i, 0, ch, TO_VICT);
+     else {
+       sprintf(buf2, "$e is mounted by %s.", PERS(RIDDEN_BY(i), ch));
+       act(buf2, FALSE, i, 0, ch, TO_VICT);
+     }
+   }
  
    found = FALSE;
    for (j = 0; !found && j < NUM_WEARS; j++)
***************
*** 244,250 ****
    if (PLR_FLAGGED(i, PLR_WRITING))
      strcat(buf, " (writing)");
  
!   if (GET_POS(i) != POS_FIGHTING)
      strcat(buf, positions[(int) GET_POS(i)]);
    else {
      if (FIGHTING(i)) {
--- 260,273 ----
    if (PLR_FLAGGED(i, PLR_WRITING))
      strcat(buf, " (writing)");
  
!   if (RIDING(i) && RIDING(i)->in_room == i->in_room) {
!     strcat(buf, " is here, mounted upon ");
!     if (RIDING(i) == ch)
!       strcat(buf, "you");
!     else
!       strcat(buf, PERS(RIDING(i), ch));
!     strcat(buf, ".");
!   } else if (GET_POS(i) != POS_FIGHTING)
      strcat(buf, positions[(int) GET_POS(i)]);
    else {
      if (FIGHTING(i)) {
***************
*** 283,288 ****
--- 306,314 ----
  
    for (i = list; i; i = i->next_in_room)
      if (ch != i) {
+       if (RIDDEN_BY(i) && RIDDEN_BY(i)->in_room == i->in_room)
+         continue;
+         
        if (CAN_SEE(ch, i))
  	list_one_char(i, ch);
        else if (IS_DARK(ch->in_room) && !CAN_SEE_IN_DARK(ch) &&
diff -c stock_src/act.movement.c src/act.movement.c
*** stock_src/act.movement.c	Mon Dec 16 05:19:56 1996
--- src/act.movement.c	Mon Dec 16 11:44:46 1996
***************
*** 34,40 ****
  int special(struct char_data *ch, int cmd, char *arg);
  void death_cry(struct char_data *ch);
  int find_eq_pos(struct char_data * ch, struct obj_data * obj, char *arg);
! 
  
  
  /* simple function to determine if char can walk on water */
--- 34,41 ----
  int special(struct char_data *ch, int cmd, char *arg);
  void death_cry(struct char_data *ch);
  int find_eq_pos(struct char_data * ch, struct obj_data * obj, char *arg);
! void dismount_char(struct char_data * ch);
! void mount_char(struct char_data *ch, struct char_data *mount);
  
  
  /* simple function to determine if char can walk on water */
***************
*** 74,80 ****
--- 75,83 ----
   */
  int do_simple_move(struct char_data *ch, int dir, int need_specials_check)
  {
+   int same_room = 0, riding = 0, ridden_by = 0;
    int was_in, need_movement;
+   int vnum;
  
    int special(struct char_data *ch, int cmd, char *arg);
  
***************
*** 85,91 ****
    if (need_specials_check && special(ch, dir + 1, ""))
      return 0;
  
!   /* charmed? */
    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master && ch->in_room == ch->master->in_room) {
      send_to_char("The thought of leaving your master makes you weep.\r\n", ch);
      act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM);
--- 88,110 ----
    if (need_specials_check && special(ch, dir + 1, ""))
      return 0;
  
!   // check if they're mounted
!   if (RIDING(ch))    riding = 1;
!   if (RIDDEN_BY(ch)) ridden_by = 1;
!   
!   // if they're mounted, are they in the same room w/ their mount(ee)?
!   if (riding && RIDING(ch)->in_room == ch->in_room)
!     same_room = 1;
!   else if (ridden_by && RIDDEN_BY(ch)->in_room == ch->in_room)
!     same_room = 1;
! 
!   // tamed mobiles cannot move about (DAK)
!   if (ridden_by && same_room && AFF_FLAGGED(ch, AFF_TAMED)) {
!     send_to_char("You've been tamed.  Now act it!\r\n", ch);
!     return 0;
!   }
! 
!   // charmed?
    if (IS_AFFECTED(ch, AFF_CHARM) && ch->master && ch->in_room == ch->master->in_room) {
      send_to_char("The thought of leaving your master makes you weep.\r\n", ch);
      act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM);
***************
*** 95,101 ****
    /* if this room or the one we're going to needs a boat, check for one */
    if ((SECT(ch->in_room) == SECT_WATER_NOSWIM) ||
        (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) {
!     if (!has_boat(ch)) {
        send_to_char("You need a boat to go there.\r\n", ch);
        return 0;
      }
--- 114,120 ----
    /* if this room or the one we're going to needs a boat, check for one */
    if ((SECT(ch->in_room) == SECT_WATER_NOSWIM) ||
        (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) {
!     if ((riding && !has_boat(RIDING(ch))) || !has_boat(ch)) {
        send_to_char("You need a boat to go there.\r\n", ch);
        return 0;
      }
***************
*** 105,150 ****
    need_movement = (movement_loss[SECT(ch->in_room)] +
  		   movement_loss[SECT(EXIT(ch, dir)->to_room)]) >> 1;
  
!   if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) {
!     if (need_specials_check && ch->master)
!       send_to_char("You are too exhausted to follow.\r\n", ch);
!     else
!       send_to_char("You are too exhausted.\r\n", ch);
! 
      return 0;
    }
    if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_ATRIUM)) {
!     if (!House_can_enter(ch, world[EXIT(ch, dir)->to_room].number)) {
        send_to_char("That's private property -- no trespassing!\r\n", ch);
        return 0;
      }
    }
!   if (IS_SET(ROOM_FLAGS(EXIT(ch, dir)->to_room), ROOM_TUNNEL) &&
!       num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) > 1) {
!     send_to_char("There isn't enough room there for more than one person!\r\n", ch);
      return 0;
    }
!   if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch))
      GET_MOVE(ch) -= need_movement;
! 
!   if (!IS_AFFECTED(ch, AFF_SNEAK)) {
      sprintf(buf2, "$n leaves %s.", dirs[dir]);
      act(buf2, TRUE, ch, 0, 0, TO_ROOM);
    }
    was_in = ch->in_room;
    char_from_room(ch);
    char_to_room(ch, world[was_in].dir_option[dir]->to_room);
  
!   if (!IS_AFFECTED(ch, AFF_SNEAK))
!     act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM);
  
    if (ch->desc != NULL)
      look_at_room(ch, 0);
  
!   if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) {
!     log_death_trap(ch);
!     death_cry(ch);
!     extract_char(ch);
      return 0;
    }
    return 1;
--- 124,251 ----
    need_movement = (movement_loss[SECT(ch->in_room)] +
  		   movement_loss[SECT(EXIT(ch, dir)->to_room)]) >> 1;
  
!   if (riding) {
!     if (GET_MOVE(RIDING(ch)) < need_movement) {
!       send_to_char("Your mount is too exhausted.\r\n", ch);
!       return 0;
!     }
!   } else {
!     if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) {
!       if (need_specials_check && ch->master)
!         send_to_char("You are too exhausted to follow.\r\n", ch);
!       else
!         send_to_char("You are too exhausted.\r\n", ch);
!       return 0;
!     }
!   }
!   
!   if (riding && GET_SKILL(ch, SKILL_RIDING) < number(1, 101)-number(-4,need_movement)) {
!     act("$N rears backwards, throwing you to the ground.", FALSE, ch, 0, RIDING(ch), TO_CHAR);
!     act("You rear backwards, throwing $n to the ground.", FALSE, ch, 0, RIDING(ch), TO_VICT);
!     act("$N rears backwards, throwing $n to the ground.", FALSE, ch, 0, RIDING(ch), TO_NOTVICT);
!     dismount_char(ch);
!     damage(ch, ch, dice(1,6), -1);
      return 0;
    }
+   
+   vnum = world[EXIT(ch, dir)->to_room].number;
+   
    if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_ATRIUM)) {
!     if (!House_can_enter(ch, vnum)) {
        send_to_char("That's private property -- no trespassing!\r\n", ch);
        return 0;
      }
    }
!   
!   if ((riding || ridden_by) && IS_SET(ROOM_FLAGS(EXIT(ch, dir)->to_room), ROOM_TUNNEL)) {
!     send_to_char("There isn't enough room there, while mounted.\r\n", ch);
      return 0;
+   } else {
+     if (IS_SET(ROOM_FLAGS(EXIT(ch, dir)->to_room), ROOM_TUNNEL) &&
+         num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) > 1) {
+       send_to_char("There isn't enough room there for more than one person!\r\n", ch);
+       return 0;
+     }
    }
!   if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch) && !(riding || ridden_by))
      GET_MOVE(ch) -= need_movement;
!   else if (riding)
!     GET_MOVE(RIDING(ch)) -= need_movement;
!   else if (ridden_by)
!     GET_MOVE(RIDDEN_BY(ch)) -= need_movement;
! 
!   if (riding) {
!     if (!IS_AFFECTED(RIDING(ch), AFF_SNEAK))
!       if (IS_AFFECTED(ch, AFF_SNEAK)) {
!         sprintf(buf2, "$n leaves %s.", dirs[dir]);
!         act(buf2, TRUE, RIDING(ch), 0, 0, TO_ROOM);
!       } else {
!         sprintf(buf2, "$n rides $N %s.", dirs[dir]);
!         act(buf2, TRUE, ch, 0, RIDING(ch), TO_NOTVICT);
!       }
!   } else if (ridden_by) {
!     if (!IS_AFFECTED(ch, AFF_SNEAK))
!       if (IS_AFFECTED(RIDDEN_BY(ch), AFF_SNEAK)) {
!         sprintf(buf2, "$n leaves %s.", dirs[dir]);
!         act(buf2, TRUE, ch, 0, 0, TO_ROOM);
!       } else {
!         sprintf(buf2, "$n rides $N %s.", dirs[dir]);
!         act(buf2, TRUE, RIDDEN_BY(ch), 0, ch, TO_NOTVICT);
!       }
!   } else if (!IS_AFFECTED(ch, AFF_SNEAK)) {
      sprintf(buf2, "$n leaves %s.", dirs[dir]);
      act(buf2, TRUE, ch, 0, 0, TO_ROOM);
    }
+   
    was_in = ch->in_room;
    char_from_room(ch);
    char_to_room(ch, world[was_in].dir_option[dir]->to_room);
  
!   if (riding && same_room && RIDING(ch)->in_room != ch->in_room) {
!     char_from_room(RIDING(ch));
!     char_to_room(RIDING(ch), ch->in_room);
!   } else if (ridden_by && same_room && RIDDEN_BY(ch)->in_room != ch->in_room) {
!     char_from_room(RIDDEN_BY(ch));
!     char_to_room(RIDDEN_BY(ch), ch->in_room);
!   }
! 
!   if (!IS_AFFECTED(ch, AFF_SNEAK)) {
!     if (riding && same_room && !IS_AFFECTED(RIDING(ch), AFF_SNEAK)) {
!       sprintf(buf2, "$n arrives from %s%s, riding $N.",
!               (dir < UP  ? "the " : ""),
!               (dir == UP ? "below": dir == DOWN ? "above" : dirs[rev_dir[dir]]));
!       act(buf2, TRUE, ch, 0, RIDING(ch), TO_ROOM);
!     } else if (ridden_by && same_room && !IS_AFFECTED(RIDDEN_BY(ch), AFF_SNEAK)) {
!       sprintf(buf2, "$n arrives from %s%s, ridden by $N.",
!       	      (dir < UP  ? "the " : ""),
!       	      (dir == UP ? "below": dir == DOWN ? "above" : dirs[rev_dir[dir]]));
!       act(buf2, TRUE, ch, 0, RIDDEN_BY(ch), TO_ROOM);
!     } else if (!riding || (riding && !same_room)) {
!       act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM);
!   }
! }
  
    if (ch->desc != NULL)
      look_at_room(ch, 0);
  
!   // DT! (Hopefully these are rare in your MUD) -dak
!   if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_DEATH)) {
!     if (GET_LEVEL(ch) < LVL_IMMORT) {
!       log_death_trap(ch);
!       death_cry(ch);
!       extract_char(ch);
!     }
!     
!     if (riding && GET_LEVEL(RIDING(ch)) < LVL_IMMORT) {
!       log_death_trap(ch);
!       death_cry(ch);
!       extract_char(ch);
!     }
!     
!     if (ridden_by && GET_LEVEL(RIDDEN_BY(ch)) < LVL_IMMORT) {
!       log_death_trap(ch);
!       death_cry(ch);
!       extract_char(ch);
!     }
      return 0;
    }
    return 1;
diff -c stock_src/act.movement.c src/act.movement.c
*** stock_src/act.movement.c	Mon Dec 16 05:19:56 1996
--- src/act.movement.c	Mon Dec 16 11:44:46 1996
***************
*** 690,692 ****
--- 791,925 ----
      }
    }
  }
+ 
+ 
+ // Mounts (DAK)
+ ACMD(do_mount) {
+   char arg[MAX_INPUT_LENGTH];
+   struct char_data *vict;
+   
+   one_argument(argument, arg);
+   
+   if (!arg || !*arg) {
+     send_to_char("Mount who?\r\n", ch);
+     return;
+   } else if (!(vict = get_char_room_vis(ch, arg))) {
+     send_to_char("There is no-one by that name here.\r\n", ch);
+     return;
+   } else if (!IS_NPC(vict) && GET_LEVEL(ch) < LVL_IMMORT) {
+     send_to_char("Ehh... no.\r\n", ch);
+     return;
+   } else if (RIDING(ch) || RIDDEN_BY(ch)) {
+     send_to_char("You are already mounted.\r\n", ch);
+     return;
+   } else if (RIDING(vict) || RIDDEN_BY(vict)) {
+     send_to_char("It is already mounted.\r\n", ch);
+     return;
+   } else if (GET_LEVEL(ch) < LVL_IMMORT && IS_NPC(vict) && !MOB_FLAGGED(vict, MOB_MOUNTABLE)) {
+     send_to_char("You can't mount that!\r\n", ch);
+     return;
+   } else if (!GET_SKILL(ch, SKILL_MOUNT)) {
+     send_to_char("First you need to learn *how* to mount.\r\n", ch);
+     return;
+   } else if (GET_SKILL(ch, SKILL_MOUNT) <= number(1, 101)) {
+     act("You try to mount $N, but slip and fall off.", FALSE, ch, 0, vict, TO_CHAR);
+     act("$n tries to mount you, but slips and falls off.", FALSE, ch, 0, vict, TO_VICT);
+     act("$n tries to mount $N, but slips and falls off.", TRUE, ch, 0, vict, TO_NOTVICT);
+     damage(ch, ch, dice(1, 2), -1);
+     return;
+   }
+   
+   act("You mount $N.", FALSE, ch, 0, vict, TO_CHAR);
+   act("$n mounts you.", FALSE, ch, 0, vict, TO_VICT);
+   act("$n mounts $N.", TRUE, ch, 0, vict, TO_NOTVICT);
+   mount_char(ch, vict);
+   
+   if (IS_NPC(vict) && !AFF_FLAGGED(vict, AFF_TAMED) && GET_SKILL(ch, SKILL_MOUNT) <= number(1, 101)) {
+     act("$N suddenly bucks upwards, throwing you violently to the ground!", FALSE, ch, 0, vict, TO_CHAR);
+     act("$n is thrown to the ground as $N violently bucks!", TRUE, ch, 0, vict, TO_NOTVICT);
+     act("You buck violently and throw $n to the ground.", FALSE, ch, 0, vict, TO_VICT);
+     dismount_char(ch);
+     damage(vict, ch, dice(1,3), -1);
+   }
+ }
+ 
+ 
+ ACMD(do_dismount) {
+   if (!RIDING(ch)) {
+     send_to_char("You aren't even riding anything.\r\n", ch);
+     return;
+   } else if (SECT(ch->in_room) == SECT_WATER_NOSWIM && !has_boat(ch)) {
+     send_to_char("Yah, right, and then drown...\r\n", ch);
+     return;
+   }
+   
+   act("You dismount $N.", FALSE, ch, 0, RIDING(ch), TO_CHAR);
+   act("$n dismounts from you.", FALSE, ch, 0, RIDING(ch), TO_VICT);
+   act("$n dismounts $N.", TRUE, ch, 0, RIDING(ch), TO_NOTVICT);
+   dismount_char(ch);
+ }
+ 
+ 
+ ACMD(do_buck) {
+   if (!RIDDEN_BY(ch)) {
+     send_to_char("You're not even being ridden!\r\n", ch);
+     return;
+   } else if (AFF_FLAGGED(ch, AFF_TAMED)) {
+     send_to_char("But you're tamed!\r\n", ch);
+     return;
+   }
+   
+   act("You quickly buck, throwing $N to the ground.", FALSE, ch, 0, RIDDEN_BY(ch), TO_CHAR);
+   act("$n quickly bucks, throwing you to the ground.", FALSE, ch, 0, RIDDEN_BY(ch), TO_VICT);
+   act("$n quickly bucks, throwing $N to the ground.", FALSE, ch, 0, RIDDEN_BY(ch), TO_NOTVICT);
+   GET_POS(RIDDEN_BY(ch)) = POS_SITTING;
+   if (number(0, 4)) {
+     send_to_char("You hit the ground hard!\r\n", RIDDEN_BY(ch));
+     damage(RIDDEN_BY(ch), RIDDEN_BY(ch), dice(2,4), -1);
+   }
+   dismount_char(ch);
+   
+   
+   // you might want to call set_fighting() or some non-sense here if you
+   // want the mount to attack the unseated rider or vice-versa.
+ }
+ 
+ 
+ ACMD(do_tame) {
+   char arg[MAX_INPUT_LENGTH];
+   struct affected_type af;
+   struct char_data *vict;
+   
+   one_argument(argument, arg);
+   
+   if (!arg || !*arg) {
+     send_to_char("Tame who?\r\n", ch);
+     return;
+   } else if (!(vict = get_char_room_vis(ch, arg))) {
+     send_to_char("They're not here.\r\n", ch);
+     return;
+   } else if (GET_LEVEL(ch) < LVL_IMMORT && IS_NPC(vict) && !MOB_FLAGGED(vict, MOB_MOUNTABLE)) {
+     send_to_char("You can't do that to them.\r\n", ch);
+     return;
+   } else if (!GET_SKILL(ch, SKILL_TAME)) {
+     send_to_char("You don't even know how to tame something.\r\n", ch);
+     return;
+   } else if (!IS_NPC(vict) && GET_LEVEL(ch) < LVL_IMMORT) {
+     send_to_char("You can't do that.\r\n", ch);
+     return;
+   } else if (GET_SKILL(ch, SKILL_TAME) <= number(1, 101)) {
+     send_to_char("You fail to tame it.\r\n", ch);
+     return;
+   }
+   
+   af.type = SKILL_TAME;
+   af.duration = 24;
+   af.modifier = 0;
+   af.location = APPLY_NONE;
+   af.bitvector = AFF_TAMED;
+   affect_join(vict, &af, FALSE, FALSE, FALSE, FALSE);
+   
+   act("You tame $N.", FALSE, ch, 0, vict, TO_CHAR);
+   act("$n tames you.", FALSE, ch, 0, vict, TO_VICT);
+   act("$n tames $N.", FALSE, ch, 0, vict, TO_NOTVICT);
+ }
\ No newline at end of file
diff -c stock_src/class.c src/class.c
*** stock_src/class.c	Mon Dec 16 05:19:56 1996
--- src/class.c	Mon Dec 16 09:39:42 1996
***************
*** 453,460 ****
   * which classes, and the minimum level the character must be to use
   * the spell or skill.
   */
! void init_spell_levels(void)
! {
    /* MAGES */
    spell_level(SPELL_MAGIC_MISSILE, CLASS_MAGIC_USER, 1);
    spell_level(SPELL_DETECT_INVIS, CLASS_MAGIC_USER, 2);
--- 453,489 ----
   * which classes, and the minimum level the character must be to use
   * the spell or skill.
   */
! void init_spell_levels(void) {
!   int i, j;
!   int cls_mage = (1 << CLASS_MAGIC_USER);
!   int cls_cleric = (1 << CLASS_CLERIC);
!   int cls_thief = (1 << CLASS_THIEF);
!   int cls_warrior = (1 << CLASS_WARRIOR);
!   
!   // Assign a spell/skill to a a whole group of classes (0 is all)
!   // For instance, { SKILL_SECOND_ATTACK, cls_mage | cls_cleric, 14 },
!   // will give mages and clerics the SECOND_ATTACK skill at level 14.
!   // More convenient than individual spell_level()s.  Use 0 to give
!   // a skill to all the classes.
!   //   -dkoepke
!   int base_skl[][3] = {
!     { SKILL_MOUNT , 0, 1 },
!     { SKILL_RIDING, 0, 1 },
!     
!     { -1, -1 } // THIS MUST END THE LIST
!   };
!   
!   // give all the base_skl[]'s
!   for (j = 0; base_skl[j][0] != -1; j++)
!     for (i = 0; i < NUM_CLASSES; i++)
!       if (!base_skl[j][1] || IS_SET(base_skl[j][1], (1 << i)))
!         spell_level(base_skl[j][0], i, base_skl[j][2]);
! 
!   // in my base patch, cls_mage, etc. are unused and that leads to
!   // annyoing warnings, so here I'll use them...
!   j = (cls_mage-cls_mage)+(cls_cleric-cls_cleric)+(cls_thief-cls_thief)+
!       (cls_warrior-cls_warrior);
!   
    /* MAGES */
    spell_level(SPELL_MAGIC_MISSILE, CLASS_MAGIC_USER, 1);
    spell_level(SPELL_DETECT_INVIS, CLASS_MAGIC_USER, 2);
***************
*** 473,478 ****
--- 502,508 ----
    spell_level(SPELL_DETECT_POISON, CLASS_MAGIC_USER, 10);
    spell_level(SPELL_COLOR_SPRAY, CLASS_MAGIC_USER, 11);
    spell_level(SPELL_ENERGY_DRAIN, CLASS_MAGIC_USER, 13);
+   spell_level(SKILL_TAME, CLASS_MAGIC_USER, 13);
    spell_level(SPELL_CURSE, CLASS_MAGIC_USER, 14);
    spell_level(SPELL_FIREBALL, CLASS_MAGIC_USER, 15);
    spell_level(SPELL_CHARM, CLASS_MAGIC_USER, 16);
***************
*** 496,501 ****
--- 526,532 ----
    spell_level(SPELL_CURE_CRITIC, CLASS_CLERIC, 9);
    spell_level(SPELL_SUMMON, CLASS_CLERIC, 10);
    spell_level(SPELL_REMOVE_POISON, CLASS_CLERIC, 10);
+   spell_level(SKILL_TAME, CLASS_CLERIC, 12);
    spell_level(SPELL_WORD_OF_RECALL, CLASS_CLERIC, 12);
    spell_level(SPELL_EARTHQUAKE, CLASS_CLERIC, 12);
    spell_level(SPELL_DISPEL_EVIL, CLASS_CLERIC, 14);
***************
*** 513,518 ****
--- 544,550 ----
    spell_level(SKILL_SNEAK, CLASS_THIEF, 1);
    spell_level(SKILL_PICK_LOCK, CLASS_THIEF, 2);
    spell_level(SKILL_BACKSTAB, CLASS_THIEF, 3);
+   spell_level(SKILL_TAME, CLASS_THIEF, 3);
    spell_level(SKILL_STEAL, CLASS_THIEF, 4);
    spell_level(SKILL_HIDE, CLASS_THIEF, 5);
    spell_level(SKILL_TRACK, CLASS_THIEF, 6);
***************
*** 521,526 ****
--- 553,559 ----
    /* WARRIORS */
    spell_level(SKILL_KICK, CLASS_WARRIOR, 1);
    spell_level(SKILL_RESCUE, CLASS_WARRIOR, 3);
+   spell_level(SKILL_TAME, CLASS_WARRIOR, 7);
    spell_level(SKILL_TRACK, CLASS_WARRIOR, 9);
    spell_level(SKILL_BASH, CLASS_WARRIOR, 12);
  }
Only in src: conf.h
diff -c stock_src/constants.c src/constants.c
*** stock_src/constants.c	Mon Dec 16 05:19:56 1996
--- src/constants.c	Mon Dec 16 10:03:12 1996
***************
*** 150,155 ****
--- 150,156 ----
    "!SLEEP",
    "!BASH",
    "!BLIND",
+   "MOUNTABLE"
    "\n"
  };
  
***************
*** 201,207 ****
    "PROT-GOOD",
    "SLEEP",
    "!TRACK",
!   "UNUSED",
    "UNUSED",
    "SNEAK",
    "HIDE",
--- 202,208 ----
    "PROT-GOOD",
    "SLEEP",
    "!TRACK",
!   "TAMED",
    "UNUSED",
    "SNEAK",
    "HIDE",
diff -c stock_src/fight.c src/fight.c
*** stock_src/fight.c	Mon Dec 16 05:19:56 1996
--- src/fight.c	Mon Dec 16 08:58:31 1996
***************
*** 662,675 ****
     * death blow, send a skill_message if one exists; if not, default to a
     * dam_message. Otherwise, always send a dam_message.
     */
!   if (!IS_WEAPON(attacktype))
!     skill_message(dam, ch, victim, attacktype);
!   else {
!     if (GET_POS(victim) == POS_DEAD || dam == 0) {
!       if (!skill_message(dam, ch, victim, attacktype))
! 	dam_message(dam, ch, victim, attacktype);
!     } else
!       dam_message(dam, ch, victim, attacktype);
    }
  
    /* Use send_to_char -- act() doesn't send message if you are DEAD. */
--- 662,677 ----
     * death blow, send a skill_message if one exists; if not, default to a
     * dam_message. Otherwise, always send a dam_message.
     */
!   if (attacktype != -1) {
!     if (!IS_WEAPON(attacktype))
!       skill_message(dam, ch, victim, attacktype);
!     else {
!       if (GET_POS(victim) == POS_DEAD || dam == 0) {
!         if (!skill_message(dam, ch, victim, attacktype))
!   	  dam_message(dam, ch, victim, attacktype);
!       } else
!         dam_message(dam, ch, victim, attacktype);
!     }
    }
  
    /* Use send_to_char -- act() doesn't send message if you are DEAD. */
diff -c stock_src/handler.c src/handler.c
*** stock_src/handler.c	Mon Dec 16 05:19:56 1996
--- src/handler.c	Mon Dec 16 09:21:27 1996
***************
*** 813,818 ****
--- 813,819 ----
    struct descriptor_data *t_desc;
    struct obj_data *obj;
    int i, freed = 0;
+   void dismount_char(struct char_data *ch);
  
    extern struct char_data *combat_list;
  
***************
*** 831,836 ****
--- 832,839 ----
    }
    if (ch->followers || ch->master)
      die_follower(ch);
+   if (RIDING(ch) || RIDDEN_BY(ch))
+     dismount_char(ch);
  
    /* Forget snooping, if applicable */
    if (ch->desc) {
***************
*** 1211,1214 ****
--- 1214,1246 ----
      return FIND_ALLDOT;
    } else
      return FIND_INDIV;
+ }
+ 
+ 
+ // dismount_char() / fr: Daniel Koepke (dkoepke@california.com)
+ //   If a character is mounted on something, we dismount them.  If
+ //   someone is mounting our character, then we dismount that someone.
+ //   This is used for cleaning up after a mount is cancelled by
+ //   something (either intentionally or by death, etc.)
+ void dismount_char(struct char_data *ch) {
+   if (RIDING(ch)) {
+     RIDDEN_BY(RIDING(ch)) = NULL;
+     RIDING(ch) = NULL;
+   }
+   
+   if (RIDDEN_BY(ch)) {
+     RIDING(RIDDEN_BY(ch)) = NULL;
+     RIDDEN_BY(ch) = NULL;
+   }
+ }
+ 
+ 
+ // mount_char() / fr: Daniel Koepke (dkoepke@california.com)
+ //   Sets _ch_ to mounting _mount_.  This does not make any checks
+ //   what-so-ever to see if the _mount_ is mountable, etc.  That is
+ //   left up to the calling function.  This does not present any
+ //   messages, either.
+ void mount_char(struct char_data *ch, struct char_data *mount) {
+   RIDING(ch) = mount;
+   RIDDEN_BY(mount) = ch;
  }
diff -c stock_src/interpreter.c src/interpreter.c
*** stock_src/interpreter.c	Mon Dec 16 05:19:56 1996
--- src/interpreter.c	Mon Dec 16 08:18:12 1996
***************
*** 61,66 ****
--- 61,67 ----
  ACMD(do_backstab);
  ACMD(do_ban);
  ACMD(do_bash);
+ ACMD(do_buck);
  ACMD(do_cast);
  ACMD(do_color);
  ACMD(do_commands);
***************
*** 69,74 ****
--- 70,76 ----
  ACMD(do_date);
  ACMD(do_dc);
  ACMD(do_diagnose);
+ ACMD(do_dismount);
  ACMD(do_display);
  ACMD(do_drink);
  ACMD(do_drop);
***************
*** 111,116 ****
--- 113,119 ----
  ACMD(do_levels);
  ACMD(do_load);
  ACMD(do_look);
+ ACMD(do_mount);
  ACMD(do_move);
  ACMD(do_not_here);
  ACMD(do_offer);
***************
*** 152,157 ****
--- 155,161 ----
  ACMD(do_steal);
  ACMD(do_switch);
  ACMD(do_syslog);
+ ACMD(do_tame);
  ACMD(do_teleport);
  ACMD(do_tell);
  ACMD(do_time);
***************
*** 226,231 ****
--- 230,236 ----
    { "bow"      , POS_STANDING, do_action   , 0, 0 },
    { "brb"      , POS_RESTING , do_action   , 0, 0 },
    { "brief"    , POS_DEAD    , do_gen_tog  , 0, SCMD_BRIEF },
+   { "buck"     , POS_STANDING, do_buck	   , 0, 0 },
    { "burp"     , POS_RESTING , do_action   , 0, 0 },
    { "buy"      , POS_STANDING, do_not_here , 0, 0 },
    { "bug"      , POS_DEAD    , do_gen_write, 0, SCMD_BUG },
***************
*** 258,263 ****
--- 263,269 ----
    { "dc"       , POS_DEAD    , do_dc       , LVL_GOD, 0 },
    { "deposit"  , POS_STANDING, do_not_here , 1, 0 },
    { "diagnose" , POS_RESTING , do_diagnose , 0, 0 },
+   { "dismount" , POS_STANDING, do_dismount , 0, 0 },
    { "display"  , POS_DEAD    , do_display  , 0, 0 },
    { "donate"   , POS_RESTING , do_drop     , 0, SCMD_DONATE },
    { "drink"    , POS_RESTING , do_drink    , 0, SCMD_DRINK },
***************
*** 350,355 ****
--- 356,362 ----
    { "motd"     , POS_DEAD    , do_gen_ps   , 0, SCMD_MOTD },
    { "mail"     , POS_STANDING, do_not_here , 1, 0 },
    { "massage"  , POS_RESTING , do_action   , 0, 0 },
+   { "mount"    , POS_STANDING, do_mount	   , 0, 0 },
    { "mute"     , POS_DEAD    , do_wizutil  , LVL_GOD, SCMD_SQUELCH },
    { "murder"   , POS_FIGHTING, do_hit      , 0, SCMD_MURDER },
  
***************
*** 474,479 ****
--- 481,487 ----
    { "tell"     , POS_DEAD    , do_tell     , 0, 0 },
    { "tackle"   , POS_RESTING , do_action   , 0, 0 },
    { "take"     , POS_RESTING , do_get      , 0, 0 },
+   { "tame"     , POS_STANDING, do_tame     , 0, 0 },
    { "tango"    , POS_STANDING, do_action   , 0, 0 },
    { "taunt"    , POS_RESTING , do_action   , 0, 0 },
    { "taste"    , POS_RESTING , do_eat      , 0, SCMD_TASTE },
Only in src: make.log
diff -c stock_src/spell_parser.c src/spell_parser.c
*** stock_src/spell_parser.c	Mon Dec 16 05:19:56 1996
--- src/spell_parser.c	Mon Dec 16 06:30:01 1996
***************
*** 127,133 ****
    "sneak",
    "steal",
    "track",			/* 140 */
!   "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 145 */
    "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 150 */
    "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 155 */
    "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 160 */
--- 127,136 ----
    "sneak",
    "steal",
    "track",			/* 140 */
!   "mount", 
!   "riding", 
!   "tame", 
!   "!UNUSED!", "!UNUSED!",	/* 145 */
    "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 150 */
    "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 155 */
    "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 160 */
***************
*** 1022,1026 ****
--- 1025,1032 ----
    skillo(SKILL_SNEAK);
    skillo(SKILL_STEAL);
    skillo(SKILL_TRACK);
+   skillo(SKILL_MOUNT);
+   skillo(SKILL_RIDING);
+   skillo(SKILL_TAME);
  }
  
diff -c stock_src/spells.h src/spells.h
*** stock_src/spells.h	Mon Dec 16 05:19:56 1996
--- src/spells.h	Mon Dec 16 06:29:14 1996
***************
*** 101,106 ****
--- 101,109 ----
  #define SKILL_SNEAK                 138 /* Reserved Skill[] DO NOT CHANGE */
  #define SKILL_STEAL                 139 /* Reserved Skill[] DO NOT CHANGE */
  #define SKILL_TRACK		    140 /* Reserved Skill[] DO NOT CHANGE */
+ #define SKILL_MOUNT		    141 // Mounting (DAK)
+ #define SKILL_RIDING		    142 // Riding (DAK)
+ #define SKILL_TAME		    143 // Ability to tame (DAK)
  /* New skills may be added here up to MAX_SKILLS (200) */
  
  
diff -c stock_src/structs.h src/structs.h
*** stock_src/structs.h	Mon Dec 16 05:19:56 1996
--- src/structs.h	Mon Dec 16 06:30:42 1996
***************
*** 148,153 ****
--- 148,154 ----
  #define MOB_NOSLEEP	 (1 << 15) /* Mob can't be slept		*/
  #define MOB_NOBASH	 (1 << 16) /* Mob can't be bashed (e.g. trees)	*/
  #define MOB_NOBLIND	 (1 << 17) /* Mob can't be blinded		*/
+ #define MOB_MOUNTABLE	 (1 << 18) // Is the mob mountable? (DAK)
  
  
  /* Preference flags: used by char_data.player_specials.pref */
***************
*** 193,199 ****
  #define AFF_PROTECT_GOOD      (1 << 13)	   /* Char protected from good  */
  #define AFF_SLEEP             (1 << 14)	   /* (R) Char magically asleep	*/
  #define AFF_NOTRACK	      (1 << 15)	   /* Char can't be tracked	*/
! #define AFF_UNUSED16	      (1 << 16)	   /* Room for future expansion	*/
  #define AFF_UNUSED17	      (1 << 17)	   /* Room for future expansion	*/
  #define AFF_SNEAK             (1 << 18)	   /* Char can move quietly	*/
  #define AFF_HIDE              (1 << 19)	   /* Char is hidden		*/
--- 194,200 ----
  #define AFF_PROTECT_GOOD      (1 << 13)	   /* Char protected from good  */
  #define AFF_SLEEP             (1 << 14)	   /* (R) Char magically asleep	*/
  #define AFF_NOTRACK	      (1 << 15)	   /* Char can't be tracked	*/
! #define AFF_TAMED   	      (1 << 16)	   // Char has been tamed (DAK)
  #define AFF_UNUSED17	      (1 << 17)	   /* Room for future expansion	*/
  #define AFF_SNEAK             (1 << 18)	   /* Char can move quietly	*/
  #define AFF_HIDE              (1 << 19)	   /* Char is hidden		*/
***************
*** 687,692 ****
--- 688,695 ----
  struct char_special_data {
     struct char_data *fighting;	/* Opponent				*/
     struct char_data *hunting;	/* Char hunted by this char		*/
+    struct char_data *riding;	// Who are they riding? (DAK)
+    struct char_data *ridden_by; // Who is riding them? (DAK)
  
     byte position;		/* Standing, fighting, sleeping, etc.	*/
  
Common subdirectories: stock_src/util and src/util
diff -c stock_src/utils.h src/utils.h
*** stock_src/utils.h	Mon Dec 16 05:19:56 1996
--- src/utils.h	Mon Dec 16 05:53:25 1996
***************
*** 255,260 ****
--- 255,262 ----
  #define IS_CARRYING_N(ch) ((ch)->char_specials.carry_items)
  #define FIGHTING(ch)	  ((ch)->char_specials.fighting)
  #define HUNTING(ch)	  ((ch)->char_specials.hunting)
+ #define RIDING(ch)	  ((ch)->char_specials.riding)		// (DAK)
+ #define RIDDEN_BY(ch)	  ((ch)->char_specials.ridden_by)	// (DAK)
  #define GET_SAVE(ch, i)	  ((ch)->char_specials.saved.apply_saving_throw[i])
  #define GET_ALIGNMENT(ch) ((ch)->char_specials.saved.alignment)
  
