diff -puN src/act.comm.c new/act.comm.c
--- src/act.comm.c	2002-11-22 21:35:44.000000000 +0100
+++ new/act.comm.c	2002-11-12 19:06:24.000000000 +0100
@@ -157,9 +157,9 @@ ACMD(do_tell)
 
   if (!*buf || !*buf2)
     send_to_char(ch, "Who do you wish to tell what??\r\n");
-  else if (GET_LEVEL(ch) < LVL_IMMORT && !(vict = get_player_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
+  else if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT && !(vict = get_player_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
     send_to_char(ch, "%s", NOPERSON);
-  else if (GET_LEVEL(ch) >= LVL_IMMORT && !(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
+  else if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT && !(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
     send_to_char(ch, "%s", NOPERSON);
   else if (is_tell_ok(ch, vict))
     perform_tell(ch, vict, buf2);
@@ -352,7 +352,7 @@ ACMD(do_page)
 
     snprintf(buf, sizeof(buf), "\007\007*$n* %s", buf2);
     if (!str_cmp(arg, "all")) {
-      if (GET_LEVEL(ch) > LVL_GOD) {
+      if (GET_LEVEL(ch, LVL_TOTAL) > LVL_GOD) {
 	for (d = descriptor_list; d; d = d->next)
 	  if (STATE(d) == CON_PLAYING && d->character)
 	    act(buf, FALSE, ch, 0, d->character, TO_VICT);
@@ -438,7 +438,7 @@ ACMD(do_gen_comm)
     return;
   }
   /* level_can_shout defined in config.c */
-  if (GET_LEVEL(ch) < level_can_shout) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < level_can_shout) {
     send_to_char(ch, "You must be at least level %d before you can %s.\r\n", level_can_shout, com_msgs[subcmd][1]);
     return;
   }
diff -puN src/act.informative.c new/act.informative.c
--- src/act.informative.c	2002-11-22 21:35:44.000000000 +0100
+++ new/act.informative.c	2002-11-26 15:17:08.000000000 +0100
@@ -44,8 +44,6 @@ ACMD(do_action);
 ACMD(do_insult);
 bitvector_t find_class_bitvector(const char *arg);
 int level_exp(int chclass, int level);
-char *title_male(int chclass, int level);
-char *title_female(int chclass, int level);
 struct time_info_data *real_time_passed(time_t t2, time_t t1);
 int compute_armor_class(struct char_data *ch);
 
@@ -243,11 +241,11 @@ void look_at_char(struct char_data *i, s
 	show_obj_to_char(GET_EQ(i, j), ch, SHOW_OBJ_SHORT);
       }
   }
-  if (ch != i && (IS_THIEF(ch) || GET_LEVEL(ch) >= LVL_IMMORT)) {
+  if (ch != i && (IS_THIEF(ch) || GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT)) {
     found = FALSE;
     act("\r\nYou attempt to peek at $s inventory:", FALSE, i, 0, ch, TO_VICT);
     for (tmp_obj = i->carrying; tmp_obj; tmp_obj = tmp_obj->next_content) {
-      if (CAN_SEE_OBJ(ch, tmp_obj) && (rand_number(0, 20) < GET_LEVEL(ch))) {
+      if (CAN_SEE_OBJ(ch, tmp_obj) && (rand_number(0, 20) < GET_LEVEL(ch, CLASS_THIEF))) {
 	show_obj_to_char(tmp_obj, ch, SHOW_OBJ_SHORT);
 	found = TRUE;
       }
@@ -397,7 +395,7 @@ ACMD(do_exits)
 
     len++;
 
-    if (GET_LEVEL(ch) >= LVL_IMMORT)
+    if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT)
       send_to_char(ch, "%-5s - [%5d] %s\r\n", dirs[door], GET_ROOM_VNUM(EXIT(ch, door)->to_room),
 		world[EXIT(ch, door)->to_room].name);
     else
@@ -731,9 +729,9 @@ ACMD(do_score)
   send_to_char(ch, "You have scored %d exp, and have %d gold coins.\r\n",
 	  GET_EXP(ch), GET_GOLD(ch));
 
-  if (GET_LEVEL(ch) < LVL_IMMORT)
+  if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)
     send_to_char(ch, "You need %d exp to reach your next level.\r\n",
-	level_exp(GET_CLASS(ch), GET_LEVEL(ch) + 1) - GET_EXP(ch));
+	level_exp(GET_CLASS(ch), GET_LEVEL(ch, LVL_TOTAL) + 1) - GET_EXP(ch));
 
   playing_time = *real_time_passed((time(0) - ch->player.time.logon) +
 				  ch->player.time.played, 0);
@@ -741,8 +739,10 @@ ACMD(do_score)
      playing_time.day, playing_time.day == 1 ? "" : "s",
      playing_time.hours, playing_time.hours == 1 ? "" : "s");
 
-  send_to_char(ch, "This ranks you as %s %s (level %d).\r\n",
-	  GET_NAME(ch), GET_TITLE(ch), GET_LEVEL(ch));
+  send_to_char(ch, "This ranks you as %s %s (level %d total).\r\n",
+	  GET_NAME(ch), GET_TITLE(ch), GET_LEVEL(ch, LVL_TOTAL));
+
+  send_to_char(ch, "You are part of the %s Guild.\r\n", pc_class_types[GET_CLASS(ch)]);
 
   switch (GET_POS(ch)) {
   case POS_DEAD:
@@ -903,7 +903,7 @@ ACMD(do_weather)
     send_to_char(ch, "The sky is %s and %s.\r\n", sky_look[weather_info.sky],
 	    weather_info.change >= 0 ? "you feel a warm wind from south" :
 	     "your foot tells you bad weather is due");
-    if (GET_LEVEL(ch) >= LVL_GOD)
+    if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_GOD)
       send_to_char(ch, "Pressure: %d (change: %d), Sky: %d (%s)\r\n",
                  weather_info.pressure,
                  weather_info.change,
@@ -1047,7 +1047,7 @@ ACMD(do_who)
     if (*name_search && str_cmp(GET_NAME(tch), name_search) &&
 	!strstr(GET_TITLE(tch), name_search))
       continue;
-    if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high)
+    if (!CAN_SEE(ch, tch) || GET_LEVEL(tch, LVL_TOTAL) < low || GET_LEVEL(tch, LVL_TOTAL) > high)
       continue;
     if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) &&
 	!PLR_FLAGGED(tch, PLR_THIEF))
@@ -1062,15 +1062,15 @@ ACMD(do_who)
       continue;
     if (short_list) {
       send_to_char(ch, "%s[%2d %s] %-12.12s%s%s",
-	      (GET_LEVEL(tch) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
-	      GET_LEVEL(tch), CLASS_ABBR(tch), GET_NAME(tch),
-	      (GET_LEVEL(tch) >= LVL_IMMORT ? CCNRM(ch, C_SPR) : ""),
+	      (GET_LEVEL(tch, LVL_TOTAL) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
+	      GET_LEVEL(tch, LVL_TOTAL), CLASS_ABBR(tch), GET_NAME(tch),
+	      (GET_LEVEL(tch, LVL_TOTAL) >= LVL_IMMORT ? CCNRM(ch, C_SPR) : ""),
 	      ((!(++num_can_see % 4)) ? "\r\n" : ""));
     } else {
       num_can_see++;
       send_to_char(ch, "%s[%2d %s] %s %s",
-	      (GET_LEVEL(tch) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
-	      GET_LEVEL(tch), CLASS_ABBR(tch), GET_NAME(tch),
+	      (GET_LEVEL(tch, LVL_TOTAL) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
+	      GET_LEVEL(tch, LVL_TOTAL), CLASS_ABBR(tch), GET_NAME(tch),
 	      GET_TITLE(tch));
 
       if (GET_INVIS_LEV(tch))
@@ -1100,7 +1100,7 @@ ACMD(do_who)
 	send_to_char(ch, " (THIEF)");
       if (PLR_FLAGGED(tch, PLR_KILLER))
 	send_to_char(ch, " (KILLER)");
-      if (GET_LEVEL(tch) >= LVL_IMMORT)
+      if (GET_LEVEL(tch, LVL_TOTAL) >= LVL_IMMORT)
 	send_to_char(ch, CCNRM(ch, C_SPR));
       send_to_char(ch, "\r\n");
     }				/* endif shortlist */
@@ -1204,21 +1204,21 @@ ACMD(do_users)
 	continue;
       if (*name_search && str_cmp(GET_NAME(tch), name_search))
 	continue;
-      if (!CAN_SEE(ch, tch) || GET_LEVEL(tch) < low || GET_LEVEL(tch) > high)
+      if (!CAN_SEE(ch, tch) || GET_LEVEL(tch, LVL_TOTAL) < low || GET_LEVEL(tch, LVL_TOTAL) > high)
 	continue;
       if (outlaws && !PLR_FLAGGED(tch, PLR_KILLER) &&
 	  !PLR_FLAGGED(tch, PLR_THIEF))
 	continue;
       if (showclass && !(showclass & (1 << GET_CLASS(tch))))
 	continue;
-      if (GET_INVIS_LEV(ch) > GET_LEVEL(ch))
+      if (GET_INVIS_LEV(ch) > GET_LEVEL(ch, LVL_TOTAL))
 	continue;
 
       if (d->original)
-	sprintf(classname, "[%2d %s]", GET_LEVEL(d->original),
+	sprintf(classname, "[%2d %s]", GET_LEVEL(d->original, LVL_TOTAL),
 		CLASS_ABBR(d->original));
       else
-	sprintf(classname, "[%2d %s]", GET_LEVEL(d->character),
+	sprintf(classname, "[%2d %s]", GET_LEVEL(d->character, LVL_TOTAL),
 		CLASS_ABBR(d->character));
     } else
       strcpy(classname, "   -   ");
@@ -1232,7 +1232,7 @@ ACMD(do_users)
     else
       strcpy(state, connected_types[STATE(d)]);
 
-    if (d->character && STATE(d) == CON_PLAYING && GET_LEVEL(d->character) < LVL_GOD)
+    if (d->character && STATE(d) == CON_PLAYING && GET_LEVEL(d->character, LVL_TOTAL) < LVL_GOD)
       sprintf(idletime, "%3d", d->character->char_specials.timer *
 	      SECS_PER_MUD_HOUR / SECS_PER_REAL_MIN);
     else
@@ -1416,7 +1416,7 @@ ACMD(do_where)
 
   one_argument(argument, arg);
 
-  if (GET_LEVEL(ch) >= LVL_IMMORT)
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT)
     perform_immort_where(ch, arg);
   else
     perform_mortal_where(ch, arg);
@@ -1436,24 +1436,12 @@ ACMD(do_levels)
   }
 
   for (i = 1; i < LVL_IMMORT; i++) {
-    nlen = snprintf(buf + len, sizeof(buf) - len, "[%2d] %8d-%-8d : ", i,
+    nlen = snprintf(buf + len, sizeof(buf) - len, "[%2d] %8d-%-8d\r\n", i,
 		level_exp(GET_CLASS(ch), i), level_exp(GET_CLASS(ch), i + 1) - 1);
     if (len + nlen >= sizeof(buf) || nlen < 0)
       break;
     len += nlen;
 
-    switch (GET_SEX(ch)) {
-    case SEX_MALE:
-    case SEX_NEUTRAL:
-      nlen = snprintf(buf + len, sizeof(buf) - len, "%s\r\n", title_male(GET_CLASS(ch), i));
-      break;
-    case SEX_FEMALE:
-      nlen = snprintf(buf + len, sizeof(buf) - len, "%s\r\n", title_female(GET_CLASS(ch), i));
-      break;
-    default:
-      nlen = snprintf(buf + len, sizeof(buf) - len, "Oh dear.  You seem to be sexless.\r\n");
-      break;
-    }
     if (len + nlen >= sizeof(buf) || nlen < 0)
       break;
     len += nlen;
@@ -1487,7 +1475,7 @@ ACMD(do_consider)
     send_to_char(ch, "Would you like to borrow a cross and a shovel?\r\n");
     return;
   }
-  diff = (GET_LEVEL(victim) - GET_LEVEL(ch));
+  diff = (GET_LEVEL(victim, LVL_TOTAL) - GET_LEVEL(ch, LVL_TOTAL));
 
   if (diff <= -10)
     send_to_char(ch, "Now where did that chicken go?\r\n");
@@ -1577,7 +1565,7 @@ ACMD(do_toggle)
   else
     sprintf(buf2, "%-3.3d", GET_WIMP_LEV(ch));	/* sprintf: OK */
 
-  if (GET_LEVEL(ch) >= LVL_IMMORT) {
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT) {
     send_to_char(ch,
           "      Buildwalk: %-3s    "
           "Clear Screen in OLC: %-3s\r\n",
@@ -1680,7 +1668,7 @@ ACMD(do_commands)
       send_to_char(ch, "Who is that?\r\n");
       return;
     }
-    if (GET_LEVEL(ch) < GET_LEVEL(vict)) {
+    if (GET_LEVEL(ch, LVL_TOTAL) < GET_LEVEL(vict, LVL_TOTAL)) {
       send_to_char(ch, "You can't see the commands of people above your level.\r\n");
       return;
     }
@@ -1701,7 +1689,7 @@ ACMD(do_commands)
   for (no = 1, cmd_num = 1; cmd_info[cmd_sort_info[cmd_num]].command[0] != '\n'; cmd_num++) {
     i = cmd_sort_info[cmd_num];
 
-    if (cmd_info[i].minimum_level < 0 || GET_LEVEL(vict) < cmd_info[i].minimum_level)
+    if (cmd_info[i].minimum_level < 0 || GET_LEVEL(vict, LVL_TOTAL) < cmd_info[i].minimum_level)
       continue;
 
     if ((cmd_info[i].minimum_level >= LVL_IMMORT) != wizhelp)
@@ -1715,4 +1703,18 @@ ACMD(do_commands)
 
   if (no % 7 != 1)
     send_to_char(ch, "\r\n");
+}
+
+ACMD(do_class)
+{
+  int j;
+	
+  send_to_char(ch, "You are part of the %s Guild, from which you are member since %d levels ago.\r\n", 
+	  pc_class_types[GET_CLASS(ch)], GET_JOINED(ch));
+	
+  for (j = 1; j < NUM_CLASSES; j++)
+    if (GET_LEVEL(ch, j) > 0)
+	  send_to_char(ch, "   - You are a level %d %s.\r\n", GET_LEVEL(ch, j), pc_class_types[j]);
+
+  send_to_char(ch, "Your total level is %d.\r\n", GET_LEVEL(ch, LVL_TOTAL));
 }
diff -puN src/act.item.c new/act.item.c
--- src/act.item.c	2002-11-22 21:35:44.000000000 +0100
+++ new/act.item.c	2002-11-13 13:11:50.000000000 +0100
@@ -679,7 +679,7 @@ void perform_give_gold(struct char_data 
     send_to_char(ch, "Heh heh heh ... we are jolly funny today, eh?\r\n");
     return;
   }
-  if ((GET_GOLD(ch) < amount) && (IS_NPC(ch) || (GET_LEVEL(ch) < LVL_GOD))) {
+  if ((GET_GOLD(ch) < amount) && (IS_NPC(ch) || (GET_LEVEL(ch, LVL_TOTAL) < LVL_GOD))) {
     send_to_char(ch, "You don't have that many coins!\r\n");
     return;
   }
@@ -691,7 +691,7 @@ void perform_give_gold(struct char_data 
   snprintf(buf, sizeof(buf), "$n gives %s to $N.", money_desc(amount));
   act(buf, TRUE, ch, 0, vict, TO_NOTVICT);
 
-  if (IS_NPC(ch) || (GET_LEVEL(ch) < LVL_GOD))
+  if (IS_NPC(ch) || (GET_LEVEL(ch, LVL_TOTAL) < LVL_GOD))
     GET_GOLD(ch) -= amount;
   GET_GOLD(vict) += amount;
 
@@ -979,7 +979,7 @@ ACMD(do_eat)
     do_drink(ch, argument, 0, SCMD_SIP);
     return;
   }
-  if ((GET_OBJ_TYPE(food) != ITEM_FOOD) && (GET_LEVEL(ch) < LVL_GOD)) {
+  if ((GET_OBJ_TYPE(food) != ITEM_FOOD) && (GET_LEVEL(ch, LVL_TOTAL) < LVL_GOD)) {
     send_to_char(ch, "You can't eat THAT!\r\n");
     return;
   }
@@ -1002,7 +1002,7 @@ ACMD(do_eat)
   if (GET_COND(ch, FULL) > 20)
     send_to_char(ch, "You are full.\r\n");
 
-  if (GET_OBJ_VAL(food, 3) && (GET_LEVEL(ch) < LVL_IMMORT)) {
+  if (GET_OBJ_VAL(food, 3) && (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)) {
     /* The crap was poisoned ! */
     send_to_char(ch, "Oops, that tasted rather strange!\r\n");
     act("$n coughs and utters some strange sounds.", FALSE, ch, 0, 0, TO_ROOM);
@@ -1380,7 +1380,7 @@ ACMD(do_wear)
   } else {
     if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying)))
       send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg1), arg1);
-    else if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
+    else if (GET_LEVEL(ch, LVL_TOTAL) < GET_OBJ_LEVEL(obj))
       send_to_char(ch, "You are not experienced enough to use that.\r\n");
     else {
       if ((where = find_eq_pos(ch, obj, arg2)) >= 0)
diff -puN src/act.movement.c new/act.movement.c
--- src/act.movement.c	2002-11-22 21:35:44.000000000 +0100
+++ new/act.movement.c	2002-11-13 13:11:50.000000000 +0100
@@ -59,7 +59,7 @@ int has_boat(struct char_data *ch)
     return (1);
 */
 
-  if (GET_LEVEL(ch) > LVL_IMMORT)
+  if (GET_LEVEL(ch, LVL_TOTAL) > LVL_IMMORT)
     return (1);
 
   if (AFF_FLAGGED(ch, AFF_WATERWALK))
@@ -151,13 +151,13 @@ int do_simple_move(struct char_data *ch,
   }
   /* Mortals and low level gods cannot enter greater god rooms. */
   if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) &&
-	GET_LEVEL(ch) < LVL_GRGOD) {
+	GET_LEVEL(ch, LVL_TOTAL) < LVL_GRGOD) {
     send_to_char(ch, "You aren't godly enough to use that room!\r\n");
     return (0);
   }
 
   /* Now we know we're allowed to go into the room. */
-  if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch))
+  if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT && !IS_NPC(ch))
     GET_MOVE(ch) -= need_movement;
 
   if (!AFF_FLAGGED(ch, AFF_SNEAK)) {
@@ -184,7 +184,7 @@ int do_simple_move(struct char_data *ch,
   if (ch->desc != NULL)
     look_at_room(ch, 0);
 
-  if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) {
+  if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT) {
     log_death_trap(ch);
     death_cry(ch);
     extract_char(ch);
@@ -495,7 +495,7 @@ ACMD(do_gen_door)
     else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) &&
 	     IS_SET(flags_door[subcmd], NEED_UNLOCKED))
       send_to_char(ch, "It seems to be locked.\r\n");
-    else if (!has_key(ch, keynum) && (GET_LEVEL(ch) < LVL_GOD) &&
+    else if (!has_key(ch, keynum) && (GET_LEVEL(ch, LVL_TOTAL) < LVL_GOD) &&
 	     ((subcmd == SCMD_LOCK) || (subcmd == SCMD_UNLOCK)))
       send_to_char(ch, "You don't seem to have the proper key.\r\n");
     else if (ok_pick(ch, keynum, DOOR_IS_PICKPROOF(ch, obj, door), subcmd))
diff -puN src/act.offensive.c new/act.offensive.c
--- src/act.offensive.c	2002-11-22 21:35:44.000000000 +0100
+++ new/act.offensive.c	2002-11-13 16:17:14.000000000 +0100
@@ -131,7 +131,7 @@ ACMD(do_kill)
   char arg[MAX_INPUT_LENGTH];
   struct char_data *vict;
 
-  if (GET_LEVEL(ch) < LVL_IMPL || IS_NPC(ch)) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL || IS_NPC(ch)) {
     do_hit(ch, argument, cmd, subcmd);
     return;
   }
@@ -285,7 +285,7 @@ ACMD(do_flee)
 	send_to_char(ch, "You flee head over heels.\r\n");
 	if (was_fighting && !IS_NPC(ch)) {
 	  loss = GET_MAX_HIT(was_fighting) - GET_HIT(was_fighting);
-	  loss *= GET_LEVEL(was_fighting);
+	  loss *= GET_LEVEL(was_fighting, LVL_TOTAL);
 	  gain_exp(ch, -loss);
 	}
       } else {
@@ -445,7 +445,7 @@ ACMD(do_kick)
   if (percent > prob) {
     damage(ch, vict, 0, SKILL_KICK);
   } else
-    damage(ch, vict, GET_LEVEL(ch) / 2, SKILL_KICK);
+    damage(ch, vict, GET_LEVEL(ch, LVL_TOTAL) / 2, SKILL_KICK);
 
   WAIT_STATE(ch, PULSE_VIOLENCE * 3);
 }
diff -puN src/act.other.c new/act.other.c
--- src/act.other.c	2002-11-22 21:35:44.000000000 +0100
+++ new/act.other.c	2002-11-26 15:05:48.000000000 +0100
@@ -73,7 +73,7 @@ ACMD(do_quit)
   if (IS_NPC(ch) || !ch->desc)
     return;
 
-  if (subcmd != SCMD_QUIT && GET_LEVEL(ch) < LVL_IMMORT)
+  if (subcmd != SCMD_QUIT && GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)
     send_to_char(ch, "You have to type quit--no less, to quit!\r\n");
   else if (GET_POS(ch) == POS_FIGHTING)
     send_to_char(ch, "No way!  You're fighting for your life!\r\n");
@@ -118,7 +118,7 @@ ACMD(do_save)
      * that guest immortals aren't trustworthy. If you've disabled guest
      * immortal advances from mortality, you may want < instead of <=.
      */
-    if (auto_save && GET_LEVEL(ch) <= LVL_IMMORT) {
+    if (auto_save && GET_LEVEL(ch, LVL_TOTAL) <= LVL_IMMORT) {
       send_to_char(ch, "Saving aliases.\r\n");
       write_aliases(ch);
       return;
@@ -162,7 +162,7 @@ ACMD(do_sneak)
     return;
 
   af.type = SKILL_SNEAK;
-  af.duration = GET_LEVEL(ch);
+  af.duration = GET_LEVEL(ch, CLASS_THIEF);
   af.modifier = 0;
   af.location = APPLY_NONE;
   af.bitvector = AFF_SNEAK;
@@ -235,7 +235,7 @@ ACMD(do_steal)
     percent -= 50;
 
   /* NO NO With Imp's and Shopkeepers, and if player thieving is not allowed */
-  if (GET_LEVEL(vict) >= LVL_IMMORT || pcsteal ||
+  if (GET_LEVEL(vict, LVL_TOTAL) >= LVL_IMMORT || pcsteal ||
       GET_MOB_SPEC(vict) == shop_keeper)
     percent = 101;		/* Failure */
 
@@ -331,7 +331,7 @@ ACMD(do_practice)
 
 ACMD(do_visible)
 {
-  if (GET_LEVEL(ch) >= LVL_IMMORT) {
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT) {
     perform_immort_vis(ch);
     return;
   }
@@ -395,7 +395,7 @@ void print_group(struct char_data *ch)
 
     if (AFF_FLAGGED(k, AFF_GROUP)) {
       snprintf(buf, sizeof(buf), "     [%3dH %3dM %3dV] [%2d %s] $N (Head of group)",
-	      GET_HIT(k), GET_MANA(k), GET_MOVE(k), GET_LEVEL(k), CLASS_ABBR(k));
+	      GET_HIT(k), GET_MANA(k), GET_MOVE(k), GET_LEVEL(k, LVL_TOTAL), CLASS_ABBR(k));
       act(buf, FALSE, ch, 0, k, TO_CHAR);
     }
 
@@ -405,7 +405,7 @@ void print_group(struct char_data *ch)
 
       snprintf(buf, sizeof(buf), "     [%3dH %3dM %3dV] [%2d %s] $N", GET_HIT(f->follower),
 	      GET_MANA(f->follower), GET_MOVE(f->follower),
-	      GET_LEVEL(f->follower), CLASS_ABBR(f->follower));
+	      GET_LEVEL(f->follower, LVL_TOTAL), CLASS_ABBR(f->follower));
       act(buf, FALSE, ch, 0, f->follower, TO_CHAR);
     }
   }
@@ -1007,7 +1007,7 @@ ACMD(do_file)
    if (!*argument) {
      strcpy(buf, "USAGE: file <option> <num lines>\r\n\r\nFile options:\r\n");
      for (j = 0, i = 1; fields[i].level; i++)
-       if (fields[i].level <= GET_LEVEL(ch))
+       if (fields[i].level <= GET_LEVEL(ch, LVL_TOTAL))
          sprintf(buf+strlen(buf), "%-15s%s\r\n", fields[i].cmd, fields[i].file);
      send_to_char(ch, buf);
      return;
@@ -1024,7 +1024,7 @@ ACMD(do_file)
      return;
    }
 
-   if (GET_LEVEL(ch) < fields[l].level) {
+   if (GET_LEVEL(ch, LVL_TOTAL) < fields[l].level) {
      send_to_char(ch, "You are not godly enough to view that file!\r\n");
      return;
    }
diff -puN src/act.wizard.c new/act.wizard.c
--- src/act.wizard.c	2002-11-22 21:37:00.000000000 +0100
+++ new/act.wizard.c	2002-11-22 14:41:24.000000000 +0100
@@ -197,7 +197,7 @@ room_rnum find_target_room(struct char_d
   }
 
   /* a location has been found -- if you're >= GRGOD, no restrictions. */
-  if (GET_LEVEL(ch) >= LVL_GRGOD)
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_GRGOD)
     return (location);
 
   if (ROOM_FLAGGED(location, ROOM_GODROOM))
@@ -284,7 +284,7 @@ ACMD(do_trans)
     else if (victim == ch)
       send_to_char(ch, "That doesn't make much sense, does it?\r\n");
     else {
-      if ((GET_LEVEL(ch) < GET_LEVEL(victim)) && !IS_NPC(victim)) {
+      if ((GET_LEVEL(ch, LVL_TOTAL) < GET_LEVEL(victim, LVL_TOTAL)) && !IS_NPC(victim)) {
 	send_to_char(ch, "Go transfer someone your own size.\r\n");
 	return;
       }
@@ -296,7 +296,7 @@ ACMD(do_trans)
       look_at_room(victim, 0);
     }
   } else {			/* Trans All */
-    if (GET_LEVEL(ch) < LVL_GRGOD) {
+    if (GET_LEVEL(ch, LVL_TOTAL) < LVL_GRGOD) {
       send_to_char(ch, "I think not.\r\n");
       return;
     }
@@ -304,7 +304,7 @@ ACMD(do_trans)
     for (i = descriptor_list; i; i = i->next)
       if (STATE(i) == CON_PLAYING && i->character && i->character != ch) {
 	victim = i->character;
-	if (GET_LEVEL(victim) >= GET_LEVEL(ch))
+	if (GET_LEVEL(victim, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL))
 	  continue;
 	act("$n disappears in a mushroom cloud.", FALSE, victim, 0, 0, TO_ROOM);
 	char_from_room(victim);
@@ -333,7 +333,7 @@ ACMD(do_teleport)
     send_to_char(ch, "%s", NOPERSON);
   else if (victim == ch)
     send_to_char(ch, "Use 'goto' to teleport yourself.\r\n");
-  else if (GET_LEVEL(victim) >= GET_LEVEL(ch))
+  else if (GET_LEVEL(victim, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL))
     send_to_char(ch, "Maybe you shouldn't do that.\r\n");
   else if (!*buf2)
     send_to_char(ch, "Where do you wish to send this person?\r\n");
@@ -624,9 +624,9 @@ void do_stat_character(struct char_data 
 
   send_to_char(ch, "L-Des: %s", k->player.long_descr ? k->player.long_descr : "<None>\r\n");
 
-  sprinttype(k->player.chclass, IS_NPC(k) ? npc_class_types : pc_class_types, buf, sizeof(buf));
+  sprinttype(k->player.currentclass, IS_NPC(k) ? npc_class_types : pc_class_types, buf, sizeof(buf));
   send_to_char(ch, "%sClass: %s, Lev: [%s%2d%s], XP: [%s%7d%s], Align: [%4d]\r\n",
-	IS_NPC(k) ? "Monster " : "", buf, CCYEL(ch, C_NRM), GET_LEVEL(k), CCNRM(ch, C_NRM),
+	IS_NPC(k) ? "Monster " : "", buf, CCYEL(ch, C_NRM), GET_LEVEL(k, LVL_TOTAL), CCNRM(ch, C_NRM),
 	CCYEL(ch, C_NRM), GET_EXP(k), CCNRM(ch, C_NRM), GET_ALIGNMENT(k));
 
   if (!IS_NPC(k)) {
@@ -645,7 +645,7 @@ void do_stat_character(struct char_data 
 	    GET_PRACTICES(k), int_app[GET_INT(k)].learn,
 	    wis_app[GET_WIS(k)].bonus);
     /*. Display OLC zone for immorts .*/
-    if (GET_LEVEL(k) >= LVL_IMMORT)
+    if (GET_LEVEL(k, LVL_TOTAL) >= LVL_IMMORT)
       send_to_char(ch, ", OLC[%d]", GET_OLC_ZONE(k));
     send_to_char(ch, "\r\n");
   }
@@ -836,7 +836,7 @@ ACMD(do_stat)
       CREATE(victim->player_specials, struct player_special_data, 1);
       if (load_char(buf2, victim) >= 0) {
 	char_to_room(victim, 0);
-	if (GET_LEVEL(victim) > GET_LEVEL(ch))
+	if (GET_LEVEL(victim, LVL_TOTAL) > GET_LEVEL(ch, LVL_TOTAL))
 	  send_to_char(ch, "Sorry, you can't do that.\r\n");
 	else
 	  do_stat_character(ch, victim);
@@ -926,13 +926,13 @@ void snoop_check(struct char_data *ch)
   if (!ch || !ch->desc)
     return;
   if (ch->desc->snooping &&
-     (GET_LEVEL(ch->desc->snooping->character) >= GET_LEVEL(ch))) {
+     (GET_LEVEL(ch->desc->snooping->character, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL))) {
     ch->desc->snooping->snoop_by = NULL;
     ch->desc->snooping = NULL;
   }
 
   if (ch->desc->snoop_by &&
-     (GET_LEVEL(ch) >= GET_LEVEL(ch->desc->snoop_by->character))) {
+     (GET_LEVEL(ch, LVL_TOTAL) >= GET_LEVEL(ch->desc->snoop_by->character, LVL_TOTAL))) {
     ch->desc->snoop_by->snooping = NULL;
     ch->desc->snoop_by = NULL;
   }
@@ -978,7 +978,7 @@ ACMD(do_snoop)
     else
       tch = victim;
 
-    if (GET_LEVEL(tch) >= GET_LEVEL(ch)) {
+    if (GET_LEVEL(tch, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL)) {
       send_to_char(ch, "You can't.\r\n");
       return;
     }
@@ -1011,11 +1011,11 @@ ACMD(do_switch)
     send_to_char(ch, "Hee hee... we are jolly funny today, eh?\r\n");
   else if (victim->desc)
     send_to_char(ch, "You can't do that, the body is already in use!\r\n");
-  else if ((GET_LEVEL(ch) < LVL_IMPL) && !IS_NPC(victim))
+  else if ((GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL) && !IS_NPC(victim))
     send_to_char(ch, "You aren't holy enough to use a mortal's body.\r\n");
-  else if (GET_LEVEL(ch) < LVL_GRGOD && ROOM_FLAGGED(IN_ROOM(victim), ROOM_GODROOM))
+  else if (GET_LEVEL(ch, LVL_TOTAL) < LVL_GRGOD && ROOM_FLAGGED(IN_ROOM(victim), ROOM_GODROOM))
     send_to_char(ch, "You are not godly enough to use that room!\r\n");
-  else if (GET_LEVEL(ch) < LVL_GRGOD && ROOM_FLAGGED(IN_ROOM(victim), ROOM_HOUSE)
+  else if (GET_LEVEL(ch, LVL_TOTAL) < LVL_GRGOD && ROOM_FLAGGED(IN_ROOM(victim), ROOM_HOUSE)
 		&& !House_can_enter(ch, GET_ROOM_VNUM(IN_ROOM(victim))))
     send_to_char(ch, "That's private property -- no trespassing!\r\n");
   else {
@@ -1172,7 +1172,7 @@ ACMD(do_purge)
   /* argument supplied. destroy single object or char */
   if (*buf) {
     if ((vict = get_char_vis(ch, buf, NULL, FIND_CHAR_ROOM)) != NULL) {
-      if (!IS_NPC(vict) && (GET_LEVEL(ch) <= GET_LEVEL(vict))) {
+      if (!IS_NPC(vict) && (GET_LEVEL(ch, LVL_TOTAL) <= GET_LEVEL(vict, LVL_TOTAL))) {
 	send_to_char(ch, "Fuuuuuuuuu!\r\n");
 	return;
       }
@@ -1273,7 +1273,7 @@ ACMD(do_advance)
     return;
   }
 
-  if (GET_LEVEL(ch) <= GET_LEVEL(victim)) {
+  if (GET_LEVEL(ch, LVL_TOTAL) <= GET_LEVEL(victim, LVL_TOTAL)) {
     send_to_char(ch, "Maybe that's not such a great idea.\r\n");
     return;
   }
@@ -1289,18 +1289,18 @@ ACMD(do_advance)
     send_to_char(ch, "%d is the highest possible level.\r\n", LVL_IMPL);
     return;
   }
-  if (newlevel > GET_LEVEL(ch)) {
+  if (newlevel > GET_LEVEL(ch, LVL_TOTAL)) {
     send_to_char(ch, "Yeah, right.\r\n");
     return;
   }
-  if (newlevel == GET_LEVEL(victim)) {
+  if (newlevel == GET_LEVEL(victim, LVL_TOTAL)) {
     send_to_char(ch, "They are already at that level.\r\n");
     return;
   }
-  oldlevel = GET_LEVEL(victim);
-  if (newlevel < GET_LEVEL(victim)) {
+  oldlevel = GET_LEVEL(victim, LVL_TOTAL);
+  if (newlevel < GET_LEVEL(victim, LVL_TOTAL)) {
     do_start(victim);
-    GET_LEVEL(victim) = newlevel;
+    GET_LEVEL(victim, LVL_TOTAL) = newlevel;
     send_to_char(victim, "You are momentarily enveloped by darkness!\r\nYou feel somewhat diminished.\r\n");
   } else {
     act("$n makes some strange gestures.\r\n"
@@ -1351,19 +1351,19 @@ ACMD(do_restore)
     send_to_char(ch, "Whom do you wish to restore?\r\n");
   else if (!(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
     send_to_char(ch, "%s", NOPERSON);
-  else if (!IS_NPC(vict) && ch != vict && GET_LEVEL(vict) >= GET_LEVEL(ch))
+  else if (!IS_NPC(vict) && ch != vict && GET_LEVEL(vict, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL))
     send_to_char(ch, "They don't need your help.\r\n");
   else {
     GET_HIT(vict) = GET_MAX_HIT(vict);
     GET_MANA(vict) = GET_MAX_MANA(vict);
     GET_MOVE(vict) = GET_MAX_MOVE(vict);
 
-    if (!IS_NPC(vict) && GET_LEVEL(ch) >= LVL_GRGOD) {
-      if (GET_LEVEL(vict) >= LVL_IMMORT)
+    if (!IS_NPC(vict) && GET_LEVEL(ch, LVL_TOTAL) >= LVL_GRGOD) {
+      if (GET_LEVEL(vict, LVL_TOTAL) >= LVL_IMMORT)
         for (i = 1; i <= MAX_SKILLS; i++)
           SET_SKILL(vict, i, 100);
 
-      if (GET_LEVEL(vict) >= LVL_GRGOD) {
+      if (GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD) {
 	vict->real_abils.str_add = 100;
 	vict->real_abils.intel = 25;
 	vict->real_abils.wis = 25;
@@ -1401,10 +1401,10 @@ void perform_immort_invis(struct char_da
   for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) {
     if (tch == ch)
       continue;
-    if (GET_LEVEL(tch) >= GET_INVIS_LEV(ch) && GET_LEVEL(tch) < level)
+    if (GET_LEVEL(tch, LVL_TOTAL) >= GET_INVIS_LEV(ch) && GET_LEVEL(tch, LVL_TOTAL) < level)
       act("You blink and suddenly realize that $n is gone.", FALSE, ch, 0,
 	  tch, TO_VICT);
-    if (GET_LEVEL(tch) < GET_INVIS_LEV(ch) && GET_LEVEL(tch) >= level)
+    if (GET_LEVEL(tch, LVL_TOTAL) < GET_INVIS_LEV(ch) && GET_LEVEL(tch, LVL_TOTAL) >= level)
       act("You suddenly realize that $n is standing beside you.", FALSE, ch, 0,
 	  tch, TO_VICT);
   }
@@ -1429,10 +1429,10 @@ ACMD(do_invis)
     if (GET_INVIS_LEV(ch) > 0)
       perform_immort_vis(ch);
     else
-      perform_immort_invis(ch, GET_LEVEL(ch));
+      perform_immort_invis(ch, GET_LEVEL(ch, LVL_TOTAL));
   } else {
     level = atoi(arg);
-    if (level > GET_LEVEL(ch))
+    if (level > GET_LEVEL(ch, LVL_TOTAL))
       send_to_char(ch, "You can't go invisible above your own level.\r\n");
     else if (level < 1)
       perform_immort_vis(ch);
@@ -1506,7 +1506,7 @@ ACMD(do_dc)
     send_to_char(ch, "No such connection.\r\n");
     return;
   }
-  if (d->character && GET_LEVEL(d->character) >= GET_LEVEL(ch)) {
+  if (d->character && GET_LEVEL(d->character, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL)) {
     if (!CAN_SEE(ch, d->character))
       send_to_char(ch, "No such connection.\r\n");
     else
@@ -1558,7 +1558,7 @@ ACMD(do_wizlock)
   one_argument(argument, arg);
   if (*arg) {
     value = atoi(arg);
-    if (value < 0 || value > GET_LEVEL(ch)) {
+    if (value < 0 || value > GET_LEVEL(ch, LVL_TOTAL)) {
       send_to_char(ch, "Invalid wizlock value.\r\n");
       return;
     }
@@ -1627,12 +1627,12 @@ ACMD(do_last)
     free_char(vict);
     return;
   }
-  if ((GET_LEVEL(vict) > GET_LEVEL(ch)) && (GET_LEVEL(ch) < LVL_IMPL)) {
+  if ((GET_LEVEL(vict, LVL_TOTAL) > GET_LEVEL(ch, LVL_TOTAL)) && (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL)) {
     send_to_char(ch, "You are not sufficiently godly for that!\r\n");
     return;
   }
   send_to_char(ch, "[%5ld] [%2d %s] %-12s : %-18s : %-20s\r\n",
-    GET_IDNUM(vict), (int) GET_LEVEL(vict),
+    GET_IDNUM(vict), (int) GET_LEVEL(vict, LVL_TOTAL),
     class_abbrevs[(int) GET_CLASS(vict)], GET_NAME(vict),
     vict->player_specials->host && *vict->player_specials->host
     ? vict->player_specials->host : "(NOHOST)",
@@ -1653,10 +1653,10 @@ ACMD(do_force)
 
   if (!*arg || !*to_force)
     send_to_char(ch, "Whom do you wish to force do what?\r\n");
-  else if ((GET_LEVEL(ch) < LVL_GRGOD) || (str_cmp("all", arg) && str_cmp("room", arg))) {
+  else if ((GET_LEVEL(ch, LVL_TOTAL) < LVL_GRGOD) || (str_cmp("all", arg) && str_cmp("room", arg))) {
     if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD)))
       send_to_char(ch, "%s", NOPERSON);
-    else if (!IS_NPC(vict) && GET_LEVEL(ch) <= GET_LEVEL(vict))
+    else if (!IS_NPC(vict) && GET_LEVEL(ch, LVL_TOTAL) <= GET_LEVEL(vict, LVL_TOTAL))
       send_to_char(ch, "No, no, no!\r\n");
     else {
       send_to_char(ch, "%s", OK);
@@ -1671,7 +1671,7 @@ ACMD(do_force)
 
     for (vict = world[IN_ROOM(ch)].people; vict; vict = next_force) {
       next_force = vict->next_in_room;
-      if (!IS_NPC(vict) && GET_LEVEL(vict) >= GET_LEVEL(ch))
+      if (!IS_NPC(vict) && GET_LEVEL(vict, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL))
 	continue;
       act(buf1, TRUE, ch, NULL, vict, TO_VICT);
       command_interpreter(vict, to_force);
@@ -1683,7 +1683,7 @@ ACMD(do_force)
     for (i = descriptor_list; i; i = next_desc) {
       next_desc = i->next;
 
-      if (STATE(i) != CON_PLAYING || !(vict = i->character) || (!IS_NPC(vict) && GET_LEVEL(vict) >= GET_LEVEL(ch)))
+      if (STATE(i) != CON_PLAYING || !(vict = i->character) || (!IS_NPC(vict) && GET_LEVEL(vict, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL)))
 	continue;
       act(buf1, TRUE, ch, NULL, vict, TO_VICT);
       command_interpreter(vict, to_force);
@@ -1717,7 +1717,7 @@ ACMD(do_wiznet)
     if (is_number(buf1)) {
       half_chop(argument+1, buf1, argument);
       level = MAX(atoi(buf1), LVL_IMMORT);
-      if (level > GET_LEVEL(ch)) {
+      if (level > GET_LEVEL(ch, LVL_TOTAL)) {
 	send_to_char(ch, "You can't wizline above your own level.\r\n");
 	return;
       }
@@ -1728,7 +1728,7 @@ ACMD(do_wiznet)
   case '@':
     send_to_char(ch, "God channel status:\r\n");
     for (any = 0, d = descriptor_list; d; d = d->next) {
-      if (STATE(d) != CON_PLAYING || GET_LEVEL(d->character) < LVL_IMMORT)
+      if (STATE(d) != CON_PLAYING || GET_LEVEL(d->character, LVL_TOTAL) < LVL_IMMORT)
         continue;
       if (!CAN_SEE(ch, d->character))
         continue;
@@ -1765,7 +1765,7 @@ ACMD(do_wiznet)
   }
 
   for (d = descriptor_list; d; d = d->next) {
-    if ((STATE(d) == CON_PLAYING) && (GET_LEVEL(d->character) >= level) &&
+    if ((STATE(d) == CON_PLAYING) && (GET_LEVEL(d->character, LVL_TOTAL) >= level) &&
 	(!PRF_FLAGGED(d->character, PRF_NOWIZ)) &&
 	(!PLR_FLAGGED(d->character, PLR_WRITING | PLR_MAILING))
 	&& (d != ch->desc || !(PRF_FLAGGED(d->character, PRF_NOREPEAT)))) {
@@ -1835,7 +1835,7 @@ ACMD(do_wizutil)
     send_to_char(ch, "There is no such player.\r\n");
   else if (IS_NPC(vict))
     send_to_char(ch, "You can't do that to a mob!\r\n");
-  else if (GET_LEVEL(vict) > GET_LEVEL(ch))
+  else if (GET_LEVEL(vict, LVL_TOTAL) > GET_LEVEL(ch, LVL_TOTAL))
     send_to_char(ch, "Hmmm...you'd better not.\r\n");
   else {
     switch (subcmd) {
@@ -1879,7 +1879,7 @@ ACMD(do_wizutil)
 	return;
       }
       SET_BIT(PLR_FLAGS(vict), PLR_FROZEN);
-      GET_FREEZE_LEV(vict) = GET_LEVEL(ch);
+      GET_FREEZE_LEV(vict) = GET_LEVEL(ch, LVL_TOTAL);
       send_to_char(vict, "A bitter wind suddenly rises and drains every erg of heat from your body!\r\nYou feel frozen!\r\n");
       send_to_char(ch, "Frozen.\r\n");
       act("A sudden cold wind conjured from nowhere freezes $n!", FALSE, vict, 0, 0, TO_ROOM);
@@ -1890,7 +1890,7 @@ ACMD(do_wizutil)
 	send_to_char(ch, "Sorry, your victim is not morbidly encased in ice at the moment.\r\n");
 	return;
       }
-      if (GET_FREEZE_LEV(vict) > GET_LEVEL(ch)) {
+      if (GET_FREEZE_LEV(vict) > GET_LEVEL(ch, LVL_TOTAL)) {
 	send_to_char(ch, "Sorry, a level %d God froze %s... you can't unfreeze %s.\r\n",
 		GET_FREEZE_LEV(vict), GET_NAME(vict), HMHR(vict));
 	return;
@@ -1973,7 +1973,7 @@ ACMD(do_show)
   if (!*argument) {
     send_to_char(ch, "Show options:\r\n");
     for (j = 0, i = 1; fields[i].level; i++)
-      if (fields[i].level <= GET_LEVEL(ch))
+      if (fields[i].level <= GET_LEVEL(ch, LVL_TOTAL))
 	send_to_char(ch, "%-15s%s", fields[i].cmd, (!(++j % 5) ? "\r\n" : ""));
     send_to_char(ch, "\r\n");
     return;
@@ -1985,7 +1985,7 @@ ACMD(do_show)
     if (!strncmp(field, fields[l].cmd, strlen(field)))
       break;
 
-  if (GET_LEVEL(ch) < fields[l].level) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < fields[l].level) {
     send_to_char(ch, "You are not godly enough for that!\r\n");
     return;
   }
@@ -2033,7 +2033,7 @@ ACMD(do_show)
       return;
     }
     send_to_char(ch, "Player: %-12s (%s) [%2d %s]\r\n", GET_NAME(vict),
-      genders[(int) GET_SEX(vict)], GET_LEVEL(vict), class_abbrevs[(int)
+      genders[(int) GET_SEX(vict)], GET_LEVEL(vict, LVL_TOTAL), class_abbrevs[(int)
       GET_CLASS(vict)]);
     send_to_char(ch, "Au: %-8d  Bal: %-8d  Exp: %-8d  Align: %-5d  Lessons: %-3d\r\n",
       GET_GOLD(vict), GET_BANK_GOLD(vict), GET_EXP(vict),
@@ -2150,7 +2150,7 @@ ACMD(do_show)
     for (d = descriptor_list; d; d = d->next) {
       if (d->snooping == NULL || d->character == NULL)
 	continue;
-      if (STATE(d) != CON_PLAYING || GET_LEVEL(ch) < GET_LEVEL(d->character))
+      if (STATE(d) != CON_PLAYING || GET_LEVEL(ch, LVL_TOTAL) < GET_LEVEL(d->character, LVL_TOTAL))
 	continue;
       if (!CAN_SEE(ch, d->character) || IN_ROOM(d->character) == NOWHERE)
 	continue;
@@ -2232,19 +2232,18 @@ ACMD(do_show)
    { "roomflag", 	LVL_GRGOD, 	PC, 	BINARY },
    { "siteok",		LVL_GRGOD, 	PC, 	BINARY },
    { "deleted", 	LVL_IMPL, 	PC, 	BINARY },
-   { "class",		LVL_GRGOD, 	BOTH, 	MISC },
-   { "nowizlist", 	LVL_GOD, 	PC, 	BINARY },  /* 40 */
-   { "quest",		LVL_GOD, 	PC, 	BINARY },
+   { "nowizlist", 	LVL_GOD, 	PC, 	BINARY },  
+   { "quest",		LVL_GOD, 	PC, 	BINARY },  /* 40 */
    { "loadroom", 	LVL_GRGOD, 	PC, 	MISC },
    { "color",		LVL_GOD, 	PC, 	BINARY },
    { "idnum",		LVL_IMPL, 	PC, 	NUMBER },
-   { "passwd",		LVL_IMPL, 	PC, 	MISC },    /* 45 */
-   { "nodelete", 	LVL_GOD, 	PC, 	BINARY },
+   { "passwd",		LVL_IMPL, 	PC, 	MISC },    
+   { "nodelete", 	LVL_GOD, 	PC, 	BINARY },  /* 45 */
    { "sex", 		LVL_GRGOD, 	BOTH, 	MISC },
    { "age",		LVL_GRGOD,	BOTH,	NUMBER },
    { "height",		LVL_GOD,	BOTH,	NUMBER },
-   { "weight",		LVL_GOD,	BOTH,	NUMBER },  /* 50 */
-   { "olc",		LVL_IMPL,	PC,	NUMBER },
+   { "weight",		LVL_GOD,	BOTH,	NUMBER },  
+   { "olc",		LVL_IMPL,	PC,	NUMBER },          /* 50 */
    { "\n", 0, BOTH, MISC }
   };
 
@@ -2257,13 +2256,13 @@ int perform_set(struct char_data *ch, st
   room_vnum rvnum;
 
   /* Check to make sure all the levels are correct */
-  if (GET_LEVEL(ch) != LVL_IMPL) {
-    if (!IS_NPC(vict) && GET_LEVEL(ch) <= GET_LEVEL(vict) && vict != ch) {
+  if (GET_LEVEL(ch, LVL_TOTAL) != LVL_IMPL) {
+    if (!IS_NPC(vict) && GET_LEVEL(ch, LVL_TOTAL) <= GET_LEVEL(vict, LVL_TOTAL) && vict != ch) {
       send_to_char(ch, "Maybe that's not such a great idea...\r\n");
       return (0);
     }
   }
-  if (GET_LEVEL(ch) < set_fields[mode].level) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < set_fields[mode].level) {
     send_to_char(ch, "You are not godly enough for that!\r\n");
     return (0);
   }
@@ -2338,7 +2337,7 @@ int perform_set(struct char_data *ch, st
     affect_total(vict);
     break;
   case 11:
-    if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
+    if (IS_NPC(vict) || GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD)
       RANGE(3, 25);
     else
       RANGE(3, 18);
@@ -2353,7 +2352,7 @@ int perform_set(struct char_data *ch, st
     affect_total(vict);
     break;
   case 13:
-    if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
+    if (IS_NPC(vict) || GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD)
       RANGE(3, 25);
     else
       RANGE(3, 18);
@@ -2361,7 +2360,7 @@ int perform_set(struct char_data *ch, st
     affect_total(vict);
     break;
   case 14:
-    if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
+    if (IS_NPC(vict) || GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD)
       RANGE(3, 25);
     else
       RANGE(3, 18);
@@ -2369,7 +2368,7 @@ int perform_set(struct char_data *ch, st
     affect_total(vict);
     break;
   case 15:
-    if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
+    if (IS_NPC(vict) || GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD)
       RANGE(3, 25);
     else
       RANGE(3, 18);
@@ -2377,7 +2376,7 @@ int perform_set(struct char_data *ch, st
     affect_total(vict);
     break;
   case 16:
-    if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
+    if (IS_NPC(vict) || GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD)
       RANGE(3, 25);
     else
       RANGE(3, 18);
@@ -2385,7 +2384,7 @@ int perform_set(struct char_data *ch, st
     affect_total(vict);
     break;
   case 17:
-    if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
+    if (IS_NPC(vict) || GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD)
       RANGE(3, 25);
     else
       RANGE(3, 18);
@@ -2414,14 +2413,14 @@ int perform_set(struct char_data *ch, st
     affect_total(vict);
     break;
   case 24:
-    if (GET_LEVEL(ch) < LVL_IMPL && ch != vict) {
+    if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL && ch != vict) {
       send_to_char(ch, "You aren't godly enough for that!\r\n");
       return (0);
     }
-    GET_INVIS_LEV(vict) = RANGE(0, GET_LEVEL(vict));
+    GET_INVIS_LEV(vict) = RANGE(0, GET_LEVEL(vict, LVL_TOTAL));
     break;
   case 25:
-    if (GET_LEVEL(ch) < LVL_IMPL && ch != vict) {
+    if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL && ch != vict) {
       send_to_char(ch, "You aren't godly enough for that!\r\n");
       return (0);
     }
@@ -2461,12 +2460,12 @@ int perform_set(struct char_data *ch, st
     SET_OR_REMOVE(PLR_FLAGS(vict), PLR_THIEF);
     break;
   case 34:
-    if (value > GET_LEVEL(ch) || value > LVL_IMPL) {
+    if (value > GET_LEVEL(ch, LVL_TOTAL) || value > LVL_IMPL) {
       send_to_char(ch, "You can't do that.\r\n");
       return (0);
     }
     RANGE(0, LVL_IMPL);
-    vict->player.level = value;
+    vict->player.level[1] = value;
     break;
   case 35:
     if ((rnum = real_room(value)) == NOWHERE) {
@@ -2487,19 +2486,12 @@ int perform_set(struct char_data *ch, st
     SET_OR_REMOVE(PLR_FLAGS(vict), PLR_DELETED);
     break;
   case 39:
-    if ((i = parse_class(*val_arg)) == CLASS_UNDEFINED) {
-      send_to_char(ch, "That is not a class.\r\n");
-      return (0);
-    }
-    GET_CLASS(vict) = i;
-    break;
-  case 40:
     SET_OR_REMOVE(PLR_FLAGS(vict), PLR_NOWIZLIST);
     break;
-  case 41:
+  case 40:
     SET_OR_REMOVE(PRF_FLAGS(vict), PRF_QUEST);
     break;
-  case 42:
+  case 41:
     if (!str_cmp(val_arg, "off")) {
       REMOVE_BIT(PLR_FLAGS(vict), PLR_LOADROOM);
     } else if (is_number(val_arg)) {
@@ -2517,20 +2509,20 @@ int perform_set(struct char_data *ch, st
       return (0);
     }
     break;
-  case 43:
+  case 42:
     SET_OR_REMOVE(PRF_FLAGS(vict), (PRF_COLOR_1 | PRF_COLOR_2));
     break;
-  case 44:
+  case 43:
     if (GET_IDNUM(ch) != 1 || !IS_NPC(vict))
       return (0);
     GET_IDNUM(vict) = value;
     break;
-  case 45:
+  case 44:
     if (GET_IDNUM(ch) > 1) {
       send_to_char(ch, "Please don't use this command, yet.\r\n");
       return (0);
     }
-    if (GET_LEVEL(vict) >= LVL_GRGOD) {
+    if (GET_LEVEL(vict, LVL_TOTAL) >= LVL_GRGOD) {
       send_to_char(ch, "You cannot change that.\r\n");
       return (0);
     }
@@ -2538,17 +2530,17 @@ int perform_set(struct char_data *ch, st
     *(GET_PASSWD(vict) + MAX_PWD_LENGTH) = '\0';
     send_to_char(ch, "Password changed to '%s'.\r\n", val_arg);
     break;
-  case 46:
+  case 45:
     SET_OR_REMOVE(PLR_FLAGS(vict), PLR_NODELETE);
     break;
-  case 47:
+  case 46:
     if ((i = search_block(val_arg, genders, FALSE)) < 0) {
       send_to_char(ch, "Must be 'male', 'female', or 'neutral'.\r\n");
       return (0);
     }
     GET_SEX(vict) = i;
     break;
-  case 48:	/* set age */
+  case 47:	/* set age */
     if (value < 2 || value > 200) {	/* Arbitrary limits. */
       send_to_char(ch, "Ages 2 to 200 accepted.\r\n");
       return (0);
@@ -2561,17 +2553,17 @@ int perform_set(struct char_data *ch, st
     vict->player.time.birth = time(0) - ((value - 17) * SECS_PER_MUD_YEAR);
     break;
 
-  case 49:	/* Blame/Thank Rick Glover. :) */
+  case 48:	/* Blame/Thank Rick Glover. :) */
     GET_HEIGHT(vict) = value;
     affect_total(vict);
     break;
 
-  case 50:
+  case 49:
     GET_WEIGHT(vict) = value;
     affect_total(vict);
     break;
 
-  case 51:
+  case 50:
     GET_OLC_ZONE(vict) = value;
     break;
 
@@ -2628,7 +2620,7 @@ ACMD(do_set)
     clear_char(cbuf);
     CREATE(cbuf->player_specials, struct player_special_data, 1);
     if ((player_i = load_char(name, cbuf)) > -1) {
-      if (GET_LEVEL(cbuf) >= GET_LEVEL(ch)) {
+      if (GET_LEVEL(cbuf, LVL_TOTAL) >= GET_LEVEL(ch, LVL_TOTAL)) {
 	free_char(cbuf);
 	send_to_char(ch, "Sorry, you can't do that.\r\n");
 	return;
@@ -2668,7 +2660,7 @@ ACMD(do_set)
 
 ACMD(do_saveall)
 {
- if (GET_LEVEL(ch) < LVL_BUILDER)
+ if (GET_LEVEL(ch, LVL_TOTAL) < LVL_BUILDER)
     send_to_char (ch, "You are not holy enough to use this privelege.\n\r");
  else {
     save_all();
diff -puN src/boards.c new/boards.c
--- src/boards.c	2002-09-26 01:45:06.000000000 +0200
+++ new/boards.c	2002-11-13 13:15:32.000000000 +0100
@@ -107,7 +107,7 @@ int find_board(struct char_data *ch)
       if (BOARD_RNUM(i) == GET_OBJ_RNUM(obj))
 	return (i);
 
-  if (GET_LEVEL(ch) >= LVL_IMMORT)
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT)
     for (obj = ch->carrying; obj; obj = obj->next_content)
       for (i = 0; i < NUM_OF_BOARDS; i++)
         if (BOARD_RNUM(i) == GET_OBJ_RNUM(obj))
@@ -191,7 +191,7 @@ int Board_write_message(int board_type, 
   time_t ct;
   char buf[MAX_INPUT_LENGTH], buf2[MAX_NAME_LENGTH + 3];
 
-  if (GET_LEVEL(ch) < WRITE_LVL(board_type)) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < WRITE_LVL(board_type)) {
     send_to_char(ch, "You are not holy enough to write on this board.\r\n");
     return (1);
   }
@@ -222,7 +222,7 @@ int Board_write_message(int board_type, 
   snprintf(buf2, sizeof(buf2), "(%s)", GET_NAME(ch));
   snprintf(buf, sizeof(buf), "%6.10s %-12s :: %s", tmstr, buf2, arg);
   NEW_MSG_INDEX(board_type).heading = strdup(buf);
-  NEW_MSG_INDEX(board_type).level = GET_LEVEL(ch);
+  NEW_MSG_INDEX(board_type).level = GET_LEVEL(ch, LVL_TOTAL);
 
   send_to_char(ch, "Write your message.  Terminate with a @ on a new line.\r\n\r\n");
   act("$n starts to write a message.", TRUE, ch, 0, 0, TO_ROOM);
@@ -248,7 +248,7 @@ int Board_show_board(int board_type, str
   if (!*tmp || !isname(tmp, board->name))
     return (0);
 
-  if (GET_LEVEL(ch) < READ_LVL(board_type)) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < READ_LVL(board_type)) {
     send_to_char(ch, "You try but fail to understand the holy words.\r\n");
     return (1);
   }
@@ -312,7 +312,7 @@ int Board_display_msg(int board_type, st
   if (!(msg = atoi(number)))
     return (0);
 
-  if (GET_LEVEL(ch) < READ_LVL(board_type)) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < READ_LVL(board_type)) {
     send_to_char(ch, "You try but fail to understand the holy words.\r\n");
     return (1);
   }
@@ -384,12 +384,12 @@ int Board_remove_msg(int board_type, str
     return (1);
   }
   snprintf(buf, sizeof(buf), "(%s)", GET_NAME(ch));
-  if (GET_LEVEL(ch) < REMOVE_LVL(board_type) &&
+  if (GET_LEVEL(ch, LVL_TOTAL) < REMOVE_LVL(board_type) &&
       !(strstr(MSG_HEADING(board_type, ind), buf))) {
     send_to_char(ch, "You are not holy enough to remove other people's messages.\r\n");
     return (1);
   }
-  if (GET_LEVEL(ch) < MSG_LEVEL(board_type, ind)) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < MSG_LEVEL(board_type, ind)) {
     send_to_char(ch, "You can't remove a message holier than yourself.\r\n");
     return (1);
   }
diff -puN src/castle.c new/castle.c
--- src/castle.c	2002-11-18 03:30:48.000000000 +0100
+++ new/castle.c	2002-04-09 14:34:36.000000000 +0200
@@ -51,7 +51,7 @@ int is_trash(struct obj_data *i);
 void fry_victim(struct char_data *ch);
 int castle_cleaner(struct char_data *ch, int cmd, int gripe);
 int castle_twin_proc(struct char_data *ch, int cmd, char *arg, int ctlnum, const char *twinname);
-void castle_mob_spec(mob_vnum mobnum, SPECIAL(*specproc));
+void castle_mob_spec(int mobnum, SPECIAL(*specproc));
 
 
 /**********************************************************************\
@@ -79,7 +79,7 @@ ACMD(do_follow);
  * NOTE: The mobile number isn't fully specified. It's only an offset
  *	from the zone's base.
  */
-void castle_mob_spec(mob_vnum mobnum, SPECIAL(*specproc))
+void castle_mob_spec(int mobnum, SPECIAL(*specproc))
 {
   mob_vnum vmv = castle_virtual(mobnum);
   mob_rnum rmr = NOBODY;
diff -puN src/class.c new/class.c
--- src/class.c	2002-04-30 23:00:34.000000000 +0200
+++ new/class.c	2002-11-26 15:33:12.000000000 +0100
@@ -40,12 +40,12 @@ void do_start(struct char_data *ch);
 int backstab_mult(int level);
 int invalid_class(struct char_data *ch, struct obj_data *obj);
 int level_exp(int chclass, int level);
-const char *title_male(int chclass, int level);
-const char *title_female(int chclass, int level);
 
 /* Names first */
 
 const char *class_abbrevs[] = {
+  "/0",
+  "Ex",
   "Mu",
   "Cl",
   "Th",
@@ -55,6 +55,8 @@ const char *class_abbrevs[] = {
 
 
 const char *pc_class_types[] = {
+  "/0",
+  "Explorer", 
   "Magic User",
   "Cleric",
   "Thief",
@@ -62,18 +64,6 @@ const char *pc_class_types[] = {
   "\n"
 };
 
-
-/* The menu for choosing a class in interpreter.c: */
-const char *class_menu =
-"\r\n"
-"Select a class:\r\n"
-"  [C]leric\r\n"
-"  [T]hief\r\n"
-"  [W]arrior\r\n"
-"  [M]agic-user\r\n";
-
-
-
 /*
  * The code to interpret a class letter -- used in interpreter.c when a
  * new character is selecting a class and by 'set class' in act.wizard.c.
@@ -150,33 +140,6 @@ int prac_params[4][NUM_CLASSES] = {
 };
 
 
-/*
- * ...And the appropriate rooms for each guildmaster/guildguard; controls
- * which types of people the various guildguards let through.  i.e., the
- * first line shows that from room 3017, only MAGIC_USERS are allowed
- * to go south.
- *
- * Don't forget to visit spec_assign.c if you create any new mobiles that
- * should be a guild master or guard so they can act appropriately. If you
- * "recycle" the existing mobs that are used in other guilds for your new
- * guild, then you don't have to change that file, only here.
- */
-struct guild_info_type guild_info[] = {
-
-/* Midgaard */
-  { CLASS_MAGIC_USER,	3017,	SCMD_SOUTH	},
-  { CLASS_CLERIC,	3004,	SCMD_NORTH	},
-  { CLASS_THIEF,	3027,	SCMD_EAST	},
-  { CLASS_WARRIOR,	3021,	SCMD_EAST	},
-
-/* Brass Dragon */
-  { -999 /* all */ ,	5065,	SCMD_WEST	},
-
-/* this must go last -- add new guards above! */
-  { -1, NOWHERE, -1}
-};
-
-
 
 /*
  * Saving throws for:
@@ -1464,7 +1427,11 @@ void roll_real_abils(struct char_data *c
 /* Some initializations for characters, including initial skills */
 void do_start(struct char_data *ch)
 {
-  GET_LEVEL(ch) = 1;
+  int j;
+
+  GET_LEVEL(ch, LVL_TOTAL) = 1;
+  for (j = 1; j < NUM_CLASSES; j++) 	
+    GET_LEVEL(ch, j) = 0;
   GET_EXP(ch) = 1;
 
   set_title(ch, NULL);
@@ -1496,7 +1463,7 @@ void do_start(struct char_data *ch)
   }
 
   advance_level(ch);
-  mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s advanced to level %d", GET_NAME(ch), GET_LEVEL(ch));
+  mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s advanced to level %d", GET_NAME(ch), GET_LEVEL(ch, LVL_TOTAL));
 
   GET_HIT(ch) = GET_MAX_HIT(ch);
   GET_MANA(ch) = GET_MAX_MANA(ch);
@@ -1526,14 +1493,14 @@ void advance_level(struct char_data *ch)
 
   case CLASS_MAGIC_USER:
     add_hp += rand_number(3, 8);
-    add_mana = rand_number(GET_LEVEL(ch), (int)(1.5 * GET_LEVEL(ch)));
+    add_mana = rand_number(GET_LEVEL(ch, CLASS_MAGIC_USER), (int)(1.5 * GET_LEVEL(ch, CLASS_MAGIC_USER)));
     add_mana = MIN(add_mana, 10);
     add_move = rand_number(0, 2);
     break;
 
   case CLASS_CLERIC:
     add_hp += rand_number(5, 10);
-    add_mana = rand_number(GET_LEVEL(ch), (int)(1.5 * GET_LEVEL(ch)));
+    add_mana = rand_number(GET_LEVEL(ch, CLASS_CLERIC), (int)(1.5 * GET_LEVEL(ch, CLASS_CLERIC)));
     add_mana = MIN(add_mana, 10);
     add_move = rand_number(0, 2);
     break;
@@ -1554,7 +1521,7 @@ void advance_level(struct char_data *ch)
   ch->points.max_hit += MAX(1, add_hp);
   ch->points.max_move += MAX(1, add_move);
 
-  if (GET_LEVEL(ch) > 1)
+  if (GET_LEVEL(ch, LVL_TOTAL) > 1)
     ch->points.max_mana += add_mana;
 
   if (IS_MAGIC_USER(ch) || IS_CLERIC(ch))
@@ -1562,7 +1529,7 @@ void advance_level(struct char_data *ch)
   else
     GET_PRACTICES(ch) += MIN(2, MAX(1, wis_app[GET_WIS(ch)].bonus));
 
-  if (GET_LEVEL(ch) >= LVL_IMMORT) {
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT) {
     for (i = 0; i < 3; i++)
       GET_COND(ch, i) = (char) -1;
     SET_BIT(PRF_FLAGS(ch), PRF_HOLYLIGHT);
@@ -1724,7 +1691,9 @@ int level_exp(int chclass, int level)
   /* Exp required for normal mortals is below */
 
   switch (chclass) {
-
+    case CLASS_EXPLORER:
+    return 10000000;
+  
     case CLASS_MAGIC_USER:
     switch (level) {
       case  0: return 0;
@@ -1888,296 +1857,5 @@ int level_exp(int chclass, int level)
 }
 
 
-/* 
- * Default titles of male characters.
- */
-const char *title_male(int chclass, int level)
-{
-  if (level <= 0 || level > LVL_IMPL)
-    return "the Man";
-  if (level == LVL_IMPL)
-    return "the Implementor";
-
-  switch (chclass) {
-
-    case CLASS_MAGIC_USER:
-    switch (level) {
-      case  1: return "the Apprentice of Magic";
-      case  2: return "the Spell Student";
-      case  3: return "the Scholar of Magic";
-      case  4: return "the Delver in Spells";
-      case  5: return "the Medium of Magic";
-      case  6: return "the Scribe of Magic";
-      case  7: return "the Seer";
-      case  8: return "the Sage";
-      case  9: return "the Illusionist";
-      case 10: return "the Abjurer";
-      case 11: return "the Invoker";
-      case 12: return "the Enchanter";
-      case 13: return "the Conjurer";
-      case 14: return "the Magician";
-      case 15: return "the Creator";
-      case 16: return "the Savant";
-      case 17: return "the Magus";
-      case 18: return "the Wizard";
-      case 19: return "the Warlock";
-      case 20: return "the Sorcerer";
-      case 21: return "the Necromancer";
-      case 22: return "the Thaumaturge";
-      case 23: return "the Student of the Occult";
-      case 24: return "the Disciple of the Uncanny";
-      case 25: return "the Minor Elemental";
-      case 26: return "the Greater Elemental";
-      case 27: return "the Crafter of Magics";
-      case 28: return "the Shaman";
-      case 29: return "the Keeper of Talismans";
-      case 30: return "the Archmage";
-      case LVL_IMMORT: return "the Immortal Warlock";
-      case LVL_GOD: return "the Avatar of Magic";
-      case LVL_GRGOD: return "the God of Magic";
-      default: return "the Mage";
-    }
-    break;
 
-    case CLASS_CLERIC:
-    switch (level) {
-      case  1: return "the Believer";
-      case  2: return "the Attendant";
-      case  3: return "the Acolyte";
-      case  4: return "the Novice";
-      case  5: return "the Missionary";
-      case  6: return "the Adept";
-      case  7: return "the Deacon";
-      case  8: return "the Vicar";
-      case  9: return "the Priest";
-      case 10: return "the Minister";
-      case 11: return "the Canon";
-      case 12: return "the Levite";
-      case 13: return "the Curate";
-      case 14: return "the Monk";
-      case 15: return "the Healer";
-      case 16: return "the Chaplain";
-      case 17: return "the Expositor";
-      case 18: return "the Bishop";
-      case 19: return "the Arch Bishop";
-      case 20: return "the Patriarch";
-      /* no one ever thought up these titles 21-30 */
-      case LVL_IMMORT: return "the Immortal Cardinal";
-      case LVL_GOD: return "the Inquisitor";
-      case LVL_GRGOD: return "the God of good and evil";
-      default: return "the Cleric";
-    }
-    break;
-
-    case CLASS_THIEF:
-    switch (level) {
-      case  1: return "the Pilferer";
-      case  2: return "the Footpad";
-      case  3: return "the Filcher";
-      case  4: return "the Pick-Pocket";
-      case  5: return "the Sneak";
-      case  6: return "the Pincher";
-      case  7: return "the Cut-Purse";
-      case  8: return "the Snatcher";
-      case  9: return "the Sharper";
-      case 10: return "the Rogue";
-      case 11: return "the Robber";
-      case 12: return "the Magsman";
-      case 13: return "the Highwayman";
-      case 14: return "the Burglar";
-      case 15: return "the Thief";
-      case 16: return "the Knifer";
-      case 17: return "the Quick-Blade";
-      case 18: return "the Killer";
-      case 19: return "the Brigand";
-      case 20: return "the Cut-Throat";
-      /* no one ever thought up these titles 21-30 */
-      case LVL_IMMORT: return "the Immortal Assasin";
-      case LVL_GOD: return "the Demi God of thieves";
-      case LVL_GRGOD: return "the God of thieves and tradesmen";
-      default: return "the Thief";
-    }
-    break;
-
-    case CLASS_WARRIOR:
-    switch(level) {
-      case  1: return "the Swordpupil";
-      case  2: return "the Recruit";
-      case  3: return "the Sentry";
-      case  4: return "the Fighter";
-      case  5: return "the Soldier";
-      case  6: return "the Warrior";
-      case  7: return "the Veteran";
-      case  8: return "the Swordsman";
-      case  9: return "the Fencer";
-      case 10: return "the Combatant";
-      case 11: return "the Hero";
-      case 12: return "the Myrmidon";
-      case 13: return "the Swashbuckler";
-      case 14: return "the Mercenary";
-      case 15: return "the Swordmaster";
-      case 16: return "the Lieutenant";
-      case 17: return "the Champion";
-      case 18: return "the Dragoon";
-      case 19: return "the Cavalier";
-      case 20: return "the Knight";
-      /* no one ever thought up these titles 21-30 */
-      case LVL_IMMORT: return "the Immortal Warlord";
-      case LVL_GOD: return "the Extirpator";
-      case LVL_GRGOD: return "the God of war";
-      default: return "the Warrior";
-    }
-    break;
-  }
-
-  /* Default title for classes which do not have titles defined */
-  return "the Classless";
-}
-
-
-/* 
- * Default titles of female characters.
- */
-const char *title_female(int chclass, int level)
-{
-  if (level <= 0 || level > LVL_IMPL)
-    return "the Woman";
-  if (level == LVL_IMPL)
-    return "the Implementress";
-
-  switch (chclass) {
-
-    case CLASS_MAGIC_USER:
-    switch (level) {
-      case  1: return "the Apprentice of Magic";
-      case  2: return "the Spell Student";
-      case  3: return "the Scholar of Magic";
-      case  4: return "the Delveress in Spells";
-      case  5: return "the Medium of Magic";
-      case  6: return "the Scribess of Magic";
-      case  7: return "the Seeress";
-      case  8: return "the Sage";
-      case  9: return "the Illusionist";
-      case 10: return "the Abjuress";
-      case 11: return "the Invoker";
-      case 12: return "the Enchantress";
-      case 13: return "the Conjuress";
-      case 14: return "the Witch";
-      case 15: return "the Creator";
-      case 16: return "the Savant";
-      case 17: return "the Craftess";
-      case 18: return "the Wizard";
-      case 19: return "the War Witch";
-      case 20: return "the Sorceress";
-      case 21: return "the Necromancress";
-      case 22: return "the Thaumaturgess";
-      case 23: return "the Student of the Occult";
-      case 24: return "the Disciple of the Uncanny";
-      case 25: return "the Minor Elementress";
-      case 26: return "the Greater Elementress";
-      case 27: return "the Crafter of Magics";
-      case 28: return "Shaman";
-      case 29: return "the Keeper of Talismans";
-      case 30: return "Archwitch";
-      case LVL_IMMORT: return "the Immortal Enchantress";
-      case LVL_GOD: return "the Empress of Magic";
-      case LVL_GRGOD: return "the Goddess of Magic";
-      default: return "the Witch";
-    }
-    break;
-
-    case CLASS_CLERIC:
-    switch (level) {
-      case  1: return "the Believer";
-      case  2: return "the Attendant";
-      case  3: return "the Acolyte";
-      case  4: return "the Novice";
-      case  5: return "the Missionary";
-      case  6: return "the Adept";
-      case  7: return "the Deaconess";
-      case  8: return "the Vicaress";
-      case  9: return "the Priestess";
-      case 10: return "the Lady Minister";
-      case 11: return "the Canon";
-      case 12: return "the Levitess";
-      case 13: return "the Curess";
-      case 14: return "the Nunne";
-      case 15: return "the Healess";
-      case 16: return "the Chaplain";
-      case 17: return "the Expositress";
-      case 18: return "the Bishop";
-      case 19: return "the Arch Lady of the Church";
-      case 20: return "the Matriarch";
-      /* no one ever thought up these titles 21-30 */
-      case LVL_IMMORT: return "the Immortal Priestess";
-      case LVL_GOD: return "the Inquisitress";
-      case LVL_GRGOD: return "the Goddess of good and evil";
-      default: return "the Cleric";
-    }
-    break;
-
-    case CLASS_THIEF:
-    switch (level) {
-      case  1: return "the Pilferess";
-      case  2: return "the Footpad";
-      case  3: return "the Filcheress";
-      case  4: return "the Pick-Pocket";
-      case  5: return "the Sneak";
-      case  6: return "the Pincheress";
-      case  7: return "the Cut-Purse";
-      case  8: return "the Snatcheress";
-      case  9: return "the Sharpress";
-      case 10: return "the Rogue";
-      case 11: return "the Robber";
-      case 12: return "the Magswoman";
-      case 13: return "the Highwaywoman";
-      case 14: return "the Burglaress";
-      case 15: return "the Thief";
-      case 16: return "the Knifer";
-      case 17: return "the Quick-Blade";
-      case 18: return "the Murderess";
-      case 19: return "the Brigand";
-      case 20: return "the Cut-Throat";
-      /* no one ever thought up these titles 21-30 */
-      case LVL_IMMORT: return "the Immortal Assasin";
-      case LVL_GOD: return "the Demi Goddess of thieves";
-      case LVL_GRGOD: return "the Goddess of thieves and tradesmen";
-      default: return "the Thief";
-    }
-    break;
-
-    case CLASS_WARRIOR:
-    switch(level) {
-      case  1: return "the Swordpupil";
-      case  2: return "the Recruit";
-      case  3: return "the Sentress";
-      case  4: return "the Fighter";
-      case  5: return "the Soldier";
-      case  6: return "the Warrior";
-      case  7: return "the Veteran";
-      case  8: return "the Swordswoman";
-      case  9: return "the Fenceress";
-      case 10: return "the Combatess";
-      case 11: return "the Heroine";
-      case 12: return "the Myrmidon";
-      case 13: return "the Swashbuckleress";
-      case 14: return "the Mercenaress";
-      case 15: return "the Swordmistress";
-      case 16: return "the Lieutenant";
-      case 17: return "the Lady Champion";
-      case 18: return "the Lady Dragoon";
-      case 19: return "the Cavalier";
-      case 20: return "the Lady Knight";
-      /* no one ever thought up these titles 21-30 */
-      case LVL_IMMORT: return "the Immortal Lady of War";
-      case LVL_GOD: return "the Queen of Destruction";
-      case LVL_GRGOD: return "the Goddess of war";
-      default: return "the Warrior";
-    }
-    break;
-  }
-
-  /* Default title for classes which do not have titles defined */
-  return "the Classless";
-}
 
diff -puN src/constants.c new/constants.c
--- src/constants.c	2002-11-22 21:35:44.000000000 +0100
+++ new/constants.c	2002-11-17 13:50:42.000000000 +0100
@@ -54,6 +54,10 @@ const char *room_bits[] = {
   "ATRIUM",
   "OLC",
   "*",				/* BFS MARK */
+  "MAGE_GUILD",
+  "CLERIC_GUILD",
+  "THIEF_GUILD",
+  "WARRIOR_GUILD",
   "\n"
 };
 
@@ -160,7 +164,8 @@ const char *action_bits[] = {
   "NO_SLEEP",
   "NO_BASH",
   "NO_BLIND",
-  "DEAD",    /* You should never see this. */
+  "DEAD",    /* You should never see this. */
+  "GUILDMASTER",
   "\n"
 };
 
diff -puN src/constants.h new/constants.h
--- src/constants.h	2002-11-22 21:35:44.000000000 +0100
+++ new/constants.h	2002-11-16 18:08:38.000000000 +0100
@@ -20,7 +20,8 @@ extern const char *container_bits[];
 extern const char *drinks[];
 extern const char *drinknames[];
 extern const char *color_liquid[];
-extern const char *fullness[];
+extern const char *fullness[];
+extern const char *pc_class_types[];
 extern const char *npc_class_types[];
 extern const char *weekdays[];
 extern const char *month_name[];
diff -puN src/db.c new/db.c
--- src/db.c	2002-11-22 21:37:00.000000000 +0100
+++ new/db.c	2002-11-26 15:08:48.000000000 +0100
@@ -107,7 +107,8 @@ void load_zones(FILE *fl, char *zonename
 void load_help(FILE *fl);
 void assign_mobiles(void);
 void assign_objects(void);
-void assign_rooms(void);
+void assign_rooms(void);
+void assign_guilds(void);
 void assign_the_shopkeepers(void);
 void build_player_index(void);
 int is_empty(zone_rnum zone_nr);
@@ -295,7 +296,7 @@ void boot_world(void)
 
   log("Renumbering zone table.");
   renum_zone_table();
-
+ 
   if (!no_specials) {
     log("Loading shops.");
     index_boot(DB_BOOT_SHP);
@@ -466,6 +467,8 @@ void boot_db(void)
     assign_mobiles();
     log("   Shopkeepers.");
     assign_the_shopkeepers();
+    log("   Guilds.");
+    assign_guilds();
     log("   Objects.");
     assign_objects();
     log("   Rooms.");
@@ -1203,7 +1206,9 @@ void parse_simple_mob(FILE *mob_f, int i
     exit(1);
   }
 
-  GET_LEVEL(mob_proto + i) = t[0];
+  GET_LEVEL(mob_proto + i, LVL_TOTAL) = t[0];
+  for (j = 1; j < NUM_CLASSES; j++)
+    GET_LEVEL(mob_proto + i, j) = 0;
   GET_HITROLL(mob_proto + i) = 20 - t[1];
   GET_AC(mob_proto + i) = 10 * t[2];
 
@@ -2310,7 +2315,7 @@ int is_empty(zone_rnum zone_nr)
      * if an immortal has nohassle off, he counts as present 
      * added for testing zone reset triggers - Welcor 
      */
-    if ((GET_LEVEL(i->character) >= LVL_IMMORT) && (PRF_FLAGGED(i->character, PRF_NOHASSLE)))
+    if ((GET_LEVEL(i->character, LVL_TOTAL) >= LVL_IMMORT) && (PRF_FLAGGED(i->character, PRF_NOHASSLE)))
       continue;
 
     return (0);
@@ -2389,7 +2394,13 @@ int load_char(char *name, struct char_da
     for(i = 1; i <= MAX_SKILLS; i++) GET_SKILL(ch, i) = 0;
     GET_SEX(ch) = PFDEF_SEX;
     GET_CLASS(ch) = PFDEF_CLASS;
-    GET_LEVEL(ch) = PFDEF_LEVEL;
+    GET_LEVEL(ch, LVL_TOTAL) = PFDEF_LEVEL;
+    GET_LEVEL(ch, CLASS_EXPLORER) = PFDEF_LEVEL;
+   	GET_LEVEL(ch, CLASS_MAGIC_USER) = PFDEF_LEVEL;
+	GET_LEVEL(ch, CLASS_CLERIC) = PFDEF_LEVEL;
+	GET_LEVEL(ch, CLASS_THIEF) = PFDEF_LEVEL;
+	GET_LEVEL(ch, CLASS_WARRIOR) = PFDEF_LEVEL;
+	GET_JOINED(ch) = PFDEF_JOINED;
     GET_HOME(ch) = PFDEF_HOMETOWN;
     GET_HEIGHT(ch) = PFDEF_HEIGHT;
     GET_WEIGHT(ch) = PFDEF_WEIGHT;
@@ -2492,11 +2503,19 @@ int load_char(char *name, struct char_da
 	  else if(!strcmp(tag, "Int ")) ch->real_abils.intel = num;
 	  else if(!strcmp(tag, "Invs")) GET_INVIS_LEV(ch) = num;
 	  break;
+	case 'J':
+	  if (!strcmp(tag, "Join")) GET_JOINED(ch) = num;
+	  break;
 	case 'L':
 	  if(!strcmp(tag, "Last")) ch->player.time.logon = num;
 	  else if(!strcmp(tag, "Lern")) GET_PRACTICES(ch) = num;
-	  else if(!strcmp(tag, "Levl")) GET_LEVEL(ch) = num;
-	  break;
+	  else if(!strcmp(tag, "Levl")) GET_LEVEL(ch, LVL_TOTAL) = num;
+	  else if(!strcmp(tag, "Lex ")) GET_LEVEL(ch, CLASS_EXPLORER) = num;
+	  else if(!strcmp(tag, "Lmu ")) GET_LEVEL(ch, CLASS_MAGIC_USER) = num;
+	  else if(!strcmp(tag, "Lcl ")) GET_LEVEL(ch, CLASS_CLERIC) = num;
+	  else if(!strcmp(tag, "Lth ")) GET_LEVEL(ch, CLASS_THIEF) = num;
+	  else if(!strcmp(tag, "Lwr ")) GET_LEVEL(ch, CLASS_WARRIOR) = num;
+	  break;
 	case 'M':
 	  if(!strcmp(tag, "Mana")) {
 	    sscanf(line, "%d/%d", &num, &num2);
@@ -2558,7 +2577,7 @@ int load_char(char *name, struct char_da
   }
   affect_total(ch);
   /* initialization for imms */
-  if(GET_LEVEL(ch) >= LVL_IMMORT) {
+  if(GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT) {
     for(i = 1; i <= MAX_SKILLS; i++) GET_SKILL(ch, i) = 100;
     GET_COND(ch, FULL) = -1;
     GET_COND(ch, THIRST) = -1;
@@ -2652,8 +2671,15 @@ void save_char(struct char_data * ch)
 #endif
     if(GET_SEX(ch) != PFDEF_SEX) fbprintf(fl, "Sex : %d\n", GET_SEX(ch));
     if(GET_CLASS(ch) != PFDEF_CLASS) fbprintf(fl, "Clas: %d\n", GET_CLASS(ch));
-    if(GET_LEVEL(ch) != PFDEF_LEVEL) fbprintf(fl, "Levl: %d\n", GET_LEVEL(ch));
-    if(GET_HOME(ch) != PFDEF_HOMETOWN) fbprintf(fl, "Home: %d\n", GET_HOME(ch));
+    if(GET_LEVEL(ch, LVL_TOTAL) != PFDEF_LEVEL) fbprintf(fl, "Levl: %d\n", GET_LEVEL(ch, LVL_TOTAL));
+
+	if(GET_LEVEL(ch, CLASS_EXPLORER) != PFDEF_LEVEL)	fbprintf(fl, "Lex : %d\n", GET_LEVEL(ch, CLASS_EXPLORER));
+   	if(GET_LEVEL(ch, CLASS_MAGIC_USER) != PFDEF_LEVEL)	fbprintf(fl, "Lmu : %d\n", GET_LEVEL(ch, CLASS_MAGIC_USER));
+	if(GET_LEVEL(ch, CLASS_CLERIC) != PFDEF_LEVEL)		fbprintf(fl, "Lcl : %d\n", GET_LEVEL(ch, CLASS_CLERIC));
+	if(GET_LEVEL(ch, CLASS_THIEF) != PFDEF_LEVEL)		fbprintf(fl, "Lth : %d\n", GET_LEVEL(ch, CLASS_THIEF));
+	if(GET_LEVEL(ch, CLASS_WARRIOR) != PFDEF_LEVEL)		fbprintf(fl, "Lwr : %d\n", GET_LEVEL(ch, CLASS_WARRIOR));
+	if(GET_JOINED(ch) != PFDEF_JOINED) fbprintf(fl, "Join: %d\n", GET_JOINED(ch));
+	if(GET_HOME(ch) != PFDEF_HOMETOWN) fbprintf(fl, "Home: %d\n", GET_HOME(ch));
     fbprintf(fl, "Brth: %d\n", ch->player.time.birth);
     fbprintf(fl, "Plyd: %d\n", ch->player.time.played);
     fbprintf(fl, "Last: %d\n", ch->player.time.logon);
@@ -2682,7 +2708,7 @@ void save_char(struct char_data * ch)
       fbprintf(fl, "Thr4: %d\n", GET_SAVE(ch, 3));
     if(GET_SAVE(ch, 4) != PFDEF_SAVETHROW)
       fbprintf(fl, "Thr5: %d\n", GET_SAVE(ch, 4));
-    if(GET_LEVEL(ch) < LVL_IMMORT) {
+    if(GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT) {
       fbprintf(fl, "Skil:\n");
       for(i = 1; i <= MAX_SKILLS; i++)
 	if(GET_SKILL(ch, i)) fbprintf(fl, "%d %d\n", i, GET_SKILL(ch, i));
@@ -2702,11 +2728,11 @@ void save_char(struct char_data * ch)
     }
     if(GET_BAD_PWS(ch) != PFDEF_BADPWS)
       fbprintf(fl, "Badp: %d\n", GET_BAD_PWS(ch));
-    if(GET_COND(ch, FULL) != PFDEF_HUNGER && GET_LEVEL(ch) < LVL_IMMORT)
+    if(GET_COND(ch, FULL) != PFDEF_HUNGER && GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)
       fbprintf(fl, "Hung: %d\n", GET_COND(ch, FULL));
-    if(GET_COND(ch, THIRST) != PFDEF_THIRST && GET_LEVEL(ch) < LVL_IMMORT)
+    if(GET_COND(ch, THIRST) != PFDEF_THIRST && GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)
       fbprintf(fl, "Thir: %d\n", GET_COND(ch, THIRST));
-    if(GET_COND(ch, DRUNK) != PFDEF_DRUNK && GET_LEVEL(ch) < LVL_IMMORT)
+    if(GET_COND(ch, DRUNK) != PFDEF_DRUNK && GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)
       fbprintf(fl, "Drnk: %d\n", GET_COND(ch, DRUNK));
     if(GET_PRACTICES(ch) != PFDEF_PRACTICES)
       fbprintf(fl, "Lern: %d\n", GET_PRACTICES(ch));
@@ -2752,9 +2778,9 @@ void save_char(struct char_data * ch)
     /* end char_to_store code */
     if((id = get_ptable_by_name(GET_NAME(ch))) < 0) return;
     /* update the player in the player index */
-    if(player_table[id].level != GET_LEVEL(ch)) {
+    if(player_table[id].level != GET_LEVEL(ch, LVL_TOTAL)) {
       save_index = TRUE;
-      player_table[id].level = GET_LEVEL(ch);
+      player_table[id].level = GET_LEVEL(ch, LVL_TOTAL);
     }
     if(player_table[id].last != ch->player.time.logon) {
       save_index = TRUE;
@@ -3080,7 +3106,7 @@ void clear_object(struct obj_data *obj)
  */
 void init_char(struct char_data *ch)
 {
-  int i;
+  int i, j;
 
   /* create a player_special structure */
   if (ch->player_specials == NULL)
@@ -3088,7 +3114,7 @@ void init_char(struct char_data *ch)
 
   /* *** if this is our first player --- he be God *** */
   if (top_of_p_table == 0) {
-    GET_LEVEL(ch) = LVL_IMPL;
+    GET_LEVEL(ch, LVL_TOTAL) = LVL_IMPL;
     GET_EXP(ch) = 7000000;
 
     /* The implementor never goes through do_start(). */
@@ -3100,6 +3126,8 @@ void init_char(struct char_data *ch)
     GET_MOVE(ch) = GET_MAX_MOVE(ch);
   }
 
+  for (j = 1; j < NUM_CLASSES; j++)
+    GET_LEVEL(ch, j) = 0;
   set_title(ch, NULL);
   ch->player.short_descr = NULL;
   ch->player.long_descr = NULL;
@@ -3137,7 +3165,7 @@ void init_char(struct char_data *ch)
     log("SYSERR: init_char: Character '%s' not found in player table.", GET_NAME(ch));
 
   for (i = 1; i <= MAX_SKILLS; i++) {
-    if (GET_LEVEL(ch) < LVL_IMPL)
+    if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL)
       SET_SKILL(ch, i, 0);
     else
       SET_SKILL(ch, i, 100);
@@ -3157,7 +3185,7 @@ void init_char(struct char_data *ch)
   ch->real_abils.cha = 25;
 
   for (i = 0; i < 3; i++)
-    GET_COND(ch, i) = (GET_LEVEL(ch) == LVL_IMPL ? -1 : 24);
+    GET_COND(ch, i) = (GET_LEVEL(ch, LVL_TOTAL) == LVL_IMPL ? -1 : 24);
 
   GET_LOADROOM(ch) = NOWHERE;
 }
diff -puN src/dg_misc.c new/dg_misc.c
--- src/dg_misc.c	2002-11-22 21:35:44.000000000 +0100
+++ new/dg_misc.c	2002-11-13 17:40:36.000000000 +0100
@@ -151,7 +151,7 @@ void do_dg_cast(void *go, struct script_
     call_magic(caster, tch, tobj, spellnum, DG_SPELL_LEVEL, CAST_SPELL);
     extract_char(caster);
   } else
-    call_magic(caster, tch, tobj, spellnum, GET_LEVEL(caster), CAST_SPELL);
+    call_magic(caster, tch, tobj, spellnum, GET_LEVEL(caster, LVL_TOTAL), CAST_SPELL);
 }
 
 
@@ -285,10 +285,10 @@ int valid_dg_target(struct char_data *ch
 {
   if (IS_NPC(ch))  
     return TRUE;  /* all npcs are allowed as targets */
-  else if (GET_LEVEL(ch) < LVL_IMMORT) 
+  else if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT) 
     return TRUE;  /* as well as all mortals */
   else if (!IS_SET(bitvector, DG_ALLOW_GODS) &&
-           GET_LEVEL(ch) >= LVL_GOD) 
+           GET_LEVEL(ch, LVL_TOTAL) >= LVL_GOD) 
     return FALSE; /* but not always the highest gods */
   else if (!PRF_FLAGGED(ch, PRF_NOHASSLE) && GET_INVIS_LEV(ch) < LVL_IMMORT)
     return TRUE;  /* the ones in between as allowed as long as they're visible, 
diff -puN src/dg_mobcmd.c new/dg_mobcmd.c
--- src/dg_mobcmd.c	2002-11-22 21:35:44.000000000 +0100
+++ new/dg_mobcmd.c	2002-11-13 17:39:54.000000000 +0100
@@ -79,7 +79,7 @@ void mob_log(char_data *mob, const char 
 ** macro to determine if a mob is permitted to use these commands
 */
 #define MOB_OR_IMPL(ch) \
-  (IS_NPC(ch) && (!(ch)->desc || GET_LEVEL((ch)->desc->original)>=LVL_IMPL))
+  (IS_NPC(ch) && (!(ch)->desc || GET_LEVEL((ch)->desc->original, LVL_TOTAL)>=LVL_IMPL))
 
 /* mob commands */
 
@@ -363,7 +363,7 @@ ACMD(do_mload)
     if (AFF_FLAGGED(ch, AFF_CHARM))
         return;
 
-    if( ch->desc && GET_LEVEL(ch->desc->original) < LVL_IMPL)
+    if( ch->desc && GET_LEVEL(ch->desc->original, LVL_TOTAL) < LVL_IMPL)
         return;
   
     two_arguments(argument, arg1, arg2);
@@ -419,7 +419,7 @@ ACMD(do_mpurge)
     if (AFF_FLAGGED(ch, AFF_CHARM))
         return;
 
-    if (ch->desc && (GET_LEVEL(ch->desc->original) < LVL_IMPL))
+    if (ch->desc && (GET_LEVEL(ch->desc->original, LVL_TOTAL) < LVL_IMPL))
         return;
   
     one_argument(argument, arg);
@@ -646,7 +646,7 @@ ACMD(do_mdamage) {
     return;
   }
   
-  if (GET_LEVEL(vict)>=LVL_IMMORT && (dam > 0)) {
+  if (GET_LEVEL(vict, LVL_TOTAL)>=LVL_IMMORT && (dam > 0)) {
     send_to_char(vict, "Being the cool immortal you are, you sidestep a trap,\r\n"
                        "obviously placed to kill you.\r\n");
     return;
@@ -680,7 +680,7 @@ ACMD(do_mforce)
     if (AFF_FLAGGED(ch, AFF_CHARM))
         return;
   
-    if (ch->desc && (GET_LEVEL(ch->desc->original) < LVL_IMPL))
+    if (ch->desc && (GET_LEVEL(ch->desc->original, LVL_TOTAL) < LVL_IMPL))
         return;
   
     argument = one_argument(argument, arg);
@@ -698,7 +698,7 @@ ACMD(do_mforce)
             if ((i->character != ch) && !i->connected &&
                 (IN_ROOM(i->character) == IN_ROOM(ch))) {
                 vch = i->character;
-                if (GET_LEVEL(vch) < GET_LEVEL(ch) && CAN_SEE(ch, vch) &&
+                if (GET_LEVEL(vch, LVL_TOTAL) < GET_LEVEL(ch, LVL_TOTAL) && CAN_SEE(ch, vch) &&
                     valid_dg_target(vch, 0)) {
                     command_interpreter(vch, argument);
                 }
@@ -741,7 +741,7 @@ ACMD(do_mhunt)
     if (AFF_FLAGGED(ch, AFF_CHARM))
         return;
   
-    if (ch->desc && (GET_LEVEL(ch->desc->original) < LVL_IMPL))
+    if (ch->desc && (GET_LEVEL(ch->desc->original, LVL_TOTAL) < LVL_IMPL))
         return;
   
     one_argument(argument, arg);
@@ -784,7 +784,7 @@ ACMD(do_mremember)
     if (AFF_FLAGGED(ch, AFF_CHARM))
         return;
   
-    if (ch->desc && (GET_LEVEL(ch->desc->original) < LVL_IMPL))
+    if (ch->desc && (GET_LEVEL(ch->desc->original, LVL_TOTAL) < LVL_IMPL))
         return;
   
     argument = one_argument(argument, arg);
@@ -836,7 +836,7 @@ ACMD(do_mforget)
     if (AFF_FLAGGED(ch, AFF_CHARM))
         return;
   
-    if (ch->desc && (GET_LEVEL(ch->desc->original) < LVL_IMPL))
+    if (ch->desc && (GET_LEVEL(ch->desc->original, LVL_TOTAL) < LVL_IMPL))
         return;
   
     one_argument(argument, arg);
diff -puN src/dg_objcmd.c new/dg_objcmd.c
--- src/dg_objcmd.c	2002-11-22 21:35:44.000000000 +0100
+++ new/dg_objcmd.c	2002-11-13 17:41:00.000000000 +0100
@@ -518,7 +518,7 @@ OCMD(do_odamage) {
     obj_log(obj, "odamage: target not found");        
     return;
   }
-  if (GET_LEVEL(ch)>=LVL_IMMORT && (dam > 0)) {
+  if (GET_LEVEL(ch, LVL_TOTAL)>=LVL_IMMORT && (dam > 0)) {
     send_to_char(ch, "Being the cool immortal you are, you sidestep a trap, obviously placed to kill you.");
     return;
   }
diff -puN src/dg_scripts.c new/dg_scripts.c
--- src/dg_scripts.c	2002-11-22 21:35:44.000000000 +0100
+++ new/dg_scripts.c	2002-11-13 17:41:46.000000000 +0100
@@ -1185,7 +1185,7 @@ void script_vlog(const char *format, va_
   for (i = descriptor_list; i; i = i->next) {
     if (STATE(i) != CON_PLAYING || IS_NPC(i->character)) /* switch */
       continue;
-    if (GET_LEVEL(i->character) < LVL_BUILDER)
+    if (GET_LEVEL(i->character, LVL_TOTAL) < LVL_BUILDER)
       continue;
     if (PLR_FLAGGED(i->character, PLR_WRITING))
       continue;
@@ -1490,7 +1490,7 @@ void find_replacement(void *go, struct s
 	strcpy(str, GET_NAME(c));
 
       else if (!str_cmp(field, "level"))
-	sprintf(str, "%d", GET_LEVEL(c));
+	sprintf(str, "%d", GET_LEVEL(c, LVL_TOTAL));
 
       else if (!str_cmp(field, "hitp"))
 	sprintf(str, "%d", GET_HIT(c));
diff -puN src/dg_wldcmd.c new/dg_wldcmd.c
--- src/dg_wldcmd.c	2002-11-22 21:35:44.000000000 +0100
+++ new/dg_wldcmd.c	2002-11-13 18:39:50.000000000 +0100
@@ -488,7 +488,7 @@ WCMD(do_wdamage) {
     return;
   }
 
-  if (GET_LEVEL(ch)>=LVL_IMMORT && (dam > 0)) {
+  if (GET_LEVEL(ch, LVL_TOTAL)>=LVL_IMMORT && (dam > 0)) {
     send_to_char(ch, "Being a god, you carefully avoid a trap.");
     return;
   }
Common subdirectories: src/doc and new/doc
diff -puN src/fight.c new/fight.c
--- src/fight.c	2002-11-22 21:35:44.000000000 +0100
+++ new/fight.c	2002-11-13 16:38:02.000000000 +0100
@@ -92,7 +92,7 @@ void appear(struct char_data *ch)
 
   REMOVE_BIT(AFF_FLAGS(ch), AFF_INVISIBLE | AFF_HIDE);
 
-  if (GET_LEVEL(ch) < LVL_IMMORT)
+  if (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)
     act("$n slowly fades into existence.", FALSE, ch, 0, 0, TO_ROOM);
   else
     act("You feel a strange presence as $n appears, seemingly from nowhere.",
@@ -460,9 +460,9 @@ void solo_gain(struct char_data *ch, str
 
   /* Calculate level-difference bonus */
   if (IS_NPC(ch))
-    exp += MAX(0, (exp * MIN(4, (GET_LEVEL(victim) - GET_LEVEL(ch)))) / 8);
+    exp += MAX(0, (exp * MIN(4, (GET_LEVEL(victim, LVL_TOTAL) - GET_LEVEL(ch, LVL_TOTAL)))) / 8);
   else
-    exp += MAX(0, (exp * MIN(8, (GET_LEVEL(victim) - GET_LEVEL(ch)))) / 8);
+    exp += MAX(0, (exp * MIN(8, (GET_LEVEL(victim, LVL_TOTAL) - GET_LEVEL(ch, LVL_TOTAL)))) / 8);
 
   exp = MAX(exp, 1);
 
@@ -626,7 +626,7 @@ int skill_message(int dam, struct char_d
       for (j = 1, msg = fight_messages[i].msg; (j < nr) && msg; j++)
 	msg = msg->next;
 
-      if (!IS_NPC(vict) && (GET_LEVEL(vict) >= LVL_IMMORT)) {
+      if (!IS_NPC(vict) && (GET_LEVEL(vict, LVL_TOTAL) >= LVL_IMMORT)) {
 	act(msg->god_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
 	act(msg->god_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT);
 	act(msg->god_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
@@ -710,7 +710,7 @@ int damage(struct char_data *ch, struct 
     return (0);
 
   /* You can't damage an immortal! */
-  if (!IS_NPC(victim) && (GET_LEVEL(victim) >= LVL_IMMORT))
+  if (!IS_NPC(victim) && (GET_LEVEL(victim, LVL_TOTAL) >= LVL_IMMORT))
     dam = 0;
 
   if (victim != ch) {
@@ -751,7 +751,7 @@ int damage(struct char_data *ch, struct 
 
   /* Gain exp for the hit */
   if (ch != victim)
-    gain_exp(ch, GET_LEVEL(victim) * dam);
+    gain_exp(ch, GET_LEVEL(victim, LVL_TOTAL) * dam);
 
   update_pos(victim);
 
@@ -862,7 +862,7 @@ int compute_thaco(struct char_data *ch, 
   int calc_thaco;
 
   if (!IS_NPC(ch))
-    calc_thaco = thaco(GET_CLASS(ch), GET_LEVEL(ch));
+    calc_thaco = thaco(GET_CLASS(ch), GET_LEVEL(ch, LVL_TOTAL));
   else		/* THAC0 for monsters is set in the HitRoll */
     calc_thaco = 20;
   calc_thaco -= str_app[STRENGTH_APPLY_INDEX(ch)].tohit;
@@ -965,7 +965,7 @@ void hit(struct char_data *ch, struct ch
     dam = MAX(1, dam);
 
     if (type == SKILL_BACKSTAB)
-      damage(ch, victim, dam * backstab_mult(GET_LEVEL(ch)), SKILL_BACKSTAB);
+      damage(ch, victim, dam * backstab_mult(GET_LEVEL(ch, LVL_TOTAL)), SKILL_BACKSTAB);
     else
       damage(ch, victim, dam, w_type);
   }
diff -puN src/genmob.c new/genmob.c
--- src/genmob.c	2002-11-22 21:35:44.000000000 +0100
+++ new/genmob.c	2002-11-13 17:33:48.000000000 +0100
@@ -394,7 +394,7 @@ char buf2[MAX_STRING_LENGTH];
   fprintf(fd,	"%s %s %d E\n"
 		"%d %d %d %dd%d+%d %dd%d+%d\n",
 		buf1, buf2, GET_ALIGNMENT(mob),
-		GET_LEVEL(mob), 20 - GET_HITROLL(mob), GET_AC(mob) / 10, GET_HIT(mob),
+		GET_LEVEL(mob, LVL_TOTAL), 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)
   );
diff -puN src/genolc.c new/genolc.c
--- src/genolc.c	2002-11-22 21:35:44.000000000 +0100
+++ new/genolc.c	2002-11-13 17:34:10.000000000 +0100
@@ -347,10 +347,10 @@ int sprintascii(char *out, bitvector_t b
 /* Can they edit a zone?  This takes a zone's vnum.   */
 int can_edit_zone(struct char_data *ch, zone_vnum number, int subcmd)
 {
-  if (GET_LEVEL(ch) >= LVL_GRGOD) /* grgods+ can edit everything */
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_GRGOD) /* grgods+ can edit everything */
     return TRUE;
 
-  if (GET_LEVEL(ch) < LVL_BUILDER) /* non-builders can't edit anything */
+  if (GET_LEVEL(ch, LVL_TOTAL) < LVL_BUILDER) /* non-builders can't edit anything */
     return FALSE;
   
   if (GET_OLC_ZONE(ch) == number) /* correct permission set */
@@ -465,7 +465,7 @@ void perform_mlist(struct char_data *ch,
       sprintf(buf, "[%5d] %-43s %5d\r\n",
               mob_index[nr].vnum,
               temp,
-              mob_proto[nr].player.level);
+              mob_proto[nr].player.level[1]);
       found++;
       strcat(pagebuf, buf);
       if (strlen(pagebuf)>MAX_STRING_LENGTH-100) {
diff -puN src/handler.c new/handler.c
--- src/handler.c	2002-11-22 21:35:44.000000000 +0100
+++ new/handler.c	2002-11-13 16:38:22.000000000 +0100
@@ -261,7 +261,7 @@ void affect_total(struct char_data *ch)
 
   /* Make certain values are between 0..25, not < 0 and not > 25! */
 
-  i = (IS_NPC(ch) || GET_LEVEL(ch) >= LVL_GRGOD) ? 25 : 18;
+  i = (IS_NPC(ch) || GET_LEVEL(ch, LVL_TOTAL) >= LVL_GRGOD) ? 25 : 18;
 
   GET_DEX(ch) = MAX(0, MIN(GET_DEX(ch), i));
   GET_INT(ch) = MAX(0, MIN(GET_INT(ch), i));
diff -puN src/house.c new/house.c
--- src/house.c	2002-11-18 03:29:54.000000000 +0100
+++ new/house.c	2002-11-13 17:09:58.000000000 +0100
@@ -33,7 +33,7 @@ int House_get_filename(room_vnum vnum, c
 int House_load(room_vnum vnum);
 int House_save(struct obj_data *obj, FILE *fp);
 void House_restore_weight(struct obj_data *obj);
-void House_delete_file(room_vnum vnum);
+void House_delete_file(int vnum);
 int find_house(room_vnum vnum);
 void House_save_control(void);
 void hcontrol_list_houses(struct char_data *ch);
@@ -148,7 +148,7 @@ void House_crashsave(room_vnum vnum)
 
 
 /* Delete a house save file */
-void House_delete_file(room_vnum vnum)
+void House_delete_file(int vnum)
 {
   char filename[MAX_INPUT_LENGTH];
   FILE *fl;
@@ -571,7 +571,7 @@ int House_can_enter(struct char_data *ch
 {
   int i, j;
 
-  if (GET_LEVEL(ch) >= LVL_GRGOD || (i = find_house(house)) == NOWHERE)
+  if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_GRGOD || (i = find_house(house)) == NOWHERE)
     return (1);
 
   switch (house_control[i].mode) {
diff -puN src/interpreter.c new/interpreter.c
--- src/interpreter.c	2002-11-22 21:37:00.000000000 +0100
+++ new/interpreter.c	2002-11-22 14:36:42.000000000 +0100
@@ -32,7 +32,6 @@
 extern room_rnum r_mortal_start_room;
 extern room_rnum r_immort_start_room;
 extern room_rnum r_frozen_start_room;
-extern const char *class_menu;
 extern char *motd;
 extern char *imotd;
 extern char *background;
@@ -106,7 +105,8 @@ ACMD(do_gen_door);
 ACMD(do_gen_ps);
 ACMD(do_gen_tog);
 ACMD(do_gen_write);
-ACMD(do_get);
+ACMD(do_get);
+ACMD(do_class);
 ACMD(do_give);
 ACMD(do_gold);
 ACMD(do_goto);
@@ -284,6 +284,7 @@ cpp_extern const struct command_info cmd
   { "check"    , POS_STANDING, do_not_here , 1, 0 },
   { "chuckle"  , POS_RESTING , do_action   , 0, 0 },
   { "clap"     , POS_RESTING , do_action   , 0, 0 },
+  { "class"    , POS_RESTING , do_class    , 1, 0 },
   { "clear"    , POS_DEAD    , do_gen_ps   , 0, SCMD_CLEAR },
   { "close"    , POS_SITTING , do_gen_door , 0, SCMD_CLOSE },
   { "cls"      , POS_DEAD    , do_gen_ps   , 0, SCMD_CLEAR },
@@ -382,6 +383,7 @@ cpp_extern const struct command_info cmd
   { "invis"    , POS_DEAD    , do_invis    , LVL_IMMORT, 0 },
 
   { "junk"     , POS_RESTING , do_drop     , 0, SCMD_JUNK },
+  { "join"     , POS_STANDING, do_not_here , 1, 0 },
 
   { "kill"     , POS_FIGHTING, do_kill     , 0, 0 },
   { "kick"     , POS_FIGHTING, do_kick     , 1, 0 },
@@ -445,6 +447,7 @@ cpp_extern const struct command_info cmd
   { "pour"     , POS_STANDING, do_pour     , 0, SCMD_POUR },
   { "pout"     , POS_RESTING , do_action   , 0, 0 },
   { "prompt"   , POS_DEAD    , do_display  , 0, 0 },
+  { "promote"  , POS_STANDING, do_not_here , 1, 0 },
   { "practice" , POS_RESTING , do_practice , 1, 0 },
   { "pray"     , POS_SITTING , do_action   , 0, 0 },
   { "puke"     , POS_RESTING , do_action   , 0, 0 },
@@ -697,12 +700,12 @@ void command_interpreter(struct char_dat
   }
   for (length = strlen(arg), cmd = 0; *cmd_info[cmd].command != '\n'; cmd++)
     if (!strncmp(cmd_info[cmd].command, arg, length))
-      if (GET_LEVEL(ch) >= cmd_info[cmd].minimum_level)
+      if (GET_LEVEL(ch, LVL_TOTAL) >= cmd_info[cmd].minimum_level)
 	break;
 
   if (*cmd_info[cmd].command == '\n')
     send_to_char(ch, "Huh?!?\r\n");
-  else if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_FROZEN) && GET_LEVEL(ch) < LVL_IMPL)
+  else if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_FROZEN) && GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL)
     send_to_char(ch, "You try, but the mind-numbing cold prevents you...\r\n");
   else if (cmd_info[cmd].command_pointer == NULL)
     send_to_char(ch, "Sorry, that command hasn't been implemented yet.\r\n");
@@ -1552,7 +1555,7 @@ void nanny(struct descriptor_data *d, ch
 	mudlog(NRM, LVL_GOD, TRUE, "Connection attempt for %s denied from %s", GET_NAME(d->character), d->host);
 	return;
       }
-      if (GET_LEVEL(d->character) < circle_restrict) {
+      if (GET_LEVEL(d->character, LVL_TOTAL) < circle_restrict) {
 	write_to_output(d, "The game is temporarily restricted.. try again later.\r\n");
 	STATE(d) = CON_CLOSE;
 	mudlog(NRM, LVL_GOD, TRUE, "Request for login denied for %s [%s] (wizlock)", GET_NAME(d->character), d->host);
@@ -1562,7 +1565,7 @@ void nanny(struct descriptor_data *d, ch
       if (perform_dupe_check(d))
 	return;
 
-      if (GET_LEVEL(d->character) >= LVL_IMMORT)
+      if (GET_LEVEL(d->character, LVL_TOTAL) >= LVL_IMMORT)
 	write_to_output(d, "%s", imotd);
       else
 	write_to_output(d, "%s", motd);
@@ -1637,19 +1640,8 @@ void nanny(struct descriptor_data *d, ch
       return;
     }
 
-    write_to_output(d, "%s\r\nClass: ", class_menu);
-    STATE(d) = CON_QCLASS;
-    break;
-
-  case CON_QCLASS:
-    load_result = parse_class(*arg);
-    if (load_result == CLASS_UNDEFINED) {
-      write_to_output(d, "\r\nThat's not a class.\r\nClass: ");
-      return;
-    } else
-      GET_CLASS(d->character) = load_result;
-
-    if (GET_PFILEPOS(d->character) < 0)
+    GET_CLASS(d->character) = CLASS_EXPLORER;
+	if (GET_PFILEPOS(d->character) < 0)
       GET_PFILEPOS(d->character) = create_entry(GET_PC_NAME(d->character));
     /* Now GET_NAME() will work properly. */
     init_char(d->character);
@@ -1680,7 +1672,7 @@ void nanny(struct descriptor_data *d, ch
       read_aliases(d->character);
 
       if (PLR_FLAGGED(d->character, PLR_INVSTART))
-	GET_INVIS_LEV(d->character) = GET_LEVEL(d->character);
+	GET_INVIS_LEV(d->character) = GET_LEVEL(d->character, LVL_TOTAL);
 
       /*
        * We have to place the character in a room before equipping them
@@ -1691,7 +1683,7 @@ void nanny(struct descriptor_data *d, ch
 
       /* If char was saved with NOWHERE, or real_room above failed... */
       if (load_room == NOWHERE) {
-	if (GET_LEVEL(d->character) >= LVL_IMMORT)
+	if (GET_LEVEL(d->character, LVL_TOTAL) >= LVL_IMMORT)
 	  load_room = r_immort_start_room;
 	else
 	  load_room = r_mortal_start_room;
@@ -1723,7 +1715,7 @@ void nanny(struct descriptor_data *d, ch
       greet_memory_mtrigger(d->character);
 
       STATE(d) = CON_PLAYING;
-      if (GET_LEVEL(d->character) == 0) {
+      if (GET_LEVEL(d->character, LVL_TOTAL) == 0) {
 	do_start(d->character);
 	send_to_char(d->character, "%s", START_MESSG);
       }
@@ -1813,7 +1805,7 @@ void nanny(struct descriptor_data *d, ch
 	STATE(d) = CON_CLOSE;
 	return;
       }
-      if (GET_LEVEL(d->character) < LVL_GRGOD)
+      if (GET_LEVEL(d->character, LVL_TOTAL) < LVL_GRGOD)
 	SET_BIT(PLR_FLAGS(d->character), PLR_DELETED);
       save_char(d->character);
       Crash_delete_file(GET_NAME(d->character));
@@ -1828,7 +1820,8 @@ void nanny(struct descriptor_data *d, ch
 	}
       write_to_output(d, "Character '%s' deleted!\r\n"
 	      "Goodbye.\r\n", GET_NAME(d->character));
-      mudlog(NRM, LVL_GOD, TRUE, "%s (lev %d) has self-deleted.", GET_NAME(d->character), GET_LEVEL(d->character));
+      mudlog(NRM, LVL_GOD, TRUE, "%s (lev %d) has self-deleted.", GET_NAME(d->character), 
+		  GET_LEVEL(d->character, LVL_TOTAL));
       STATE(d) = CON_CLOSE;
       return;
     } else {
diff -puN src/limits.c new/limits.c
--- src/limits.c	2002-11-22 21:35:44.000000000 +0100
+++ new/limits.c	2002-11-26 15:23:08.000000000 +0100
@@ -37,8 +37,6 @@ void run_autowiz(void);
 
 void Crash_rentsave(struct char_data *ch, int cost);
 int level_exp(int chclass, int level);
-char *title_male(int chclass, int level);
-char *title_female(int chclass, int level);
 void update_char_objects(struct char_data *ch);	/* handler.c */
 void reboot_wizlists(void);
 
@@ -82,7 +80,7 @@ int mana_gain(struct char_data *ch)
 
   if (IS_NPC(ch)) {
     /* Neat and fast */
-    gain = GET_LEVEL(ch);
+    gain = GET_LEVEL(ch, LVL_TOTAL);
   } else {
     gain = graf(age(ch)->year, 4, 8, 12, 16, 12, 10, 8);
 
@@ -124,7 +122,7 @@ int hit_gain(struct char_data *ch)
 
   if (IS_NPC(ch)) {
     /* Neat and fast */
-    gain = GET_LEVEL(ch);
+    gain = GET_LEVEL(ch, LVL_TOTAL);
   } else {
 
     gain = graf(age(ch)->year, 8, 12, 20, 32, 16, 10, 4);
@@ -169,7 +167,7 @@ int move_gain(struct char_data *ch)
 
   if (IS_NPC(ch)) {
     /* Neat and fast */
-    gain = GET_LEVEL(ch);
+    gain = GET_LEVEL(ch, LVL_TOTAL);
   } else {
     gain = graf(age(ch)->year, 16, 20, 24, 20, 16, 12, 10);
 
@@ -201,27 +199,27 @@ int move_gain(struct char_data *ch)
   return (gain);
 }
 
-
-
-void set_title(struct char_data *ch, char *title)
-{
-  if (title == NULL) {
-    if (GET_SEX(ch) == SEX_FEMALE)
-      title = title_female(GET_CLASS(ch), GET_LEVEL(ch));
-    else
-      title = title_male(GET_CLASS(ch), GET_LEVEL(ch));
-  }
-
-  if (strlen(title) > MAX_TITLE_LENGTH)
-    title[MAX_TITLE_LENGTH] = '\0';
-
-  if (GET_TITLE(ch) != NULL)
-    free(GET_TITLE(ch));
-
-  GET_TITLE(ch) = strdup(title);
-}
-
-
+
+void set_title(struct char_data * ch, char *title)
+{
+   
+  if (title == NULL) {
+    if (GET_LEVEL(ch, LVL_TOTAL) == LVL_IMPL)
+      title = "the Implementor";
+     else 
+	  title = "the newbie explorer";
+  }
+
+  if (strlen(title) > MAX_TITLE_LENGTH)
+    title[MAX_TITLE_LENGTH] = '\0';
+
+  if (GET_TITLE(ch) != NULL)
+    free(GET_TITLE(ch));
+
+  GET_TITLE(ch) = strdup(title);
+}
+
+
 void run_autowiz(void)
 {
 #if defined(CIRCLE_UNIX) || defined(CIRCLE_WINDOWS)
@@ -255,7 +253,7 @@ void gain_exp(struct char_data *ch, int 
   int is_altered = FALSE;
   int num_levels = 0;
 
-  if (!IS_NPC(ch) && ((GET_LEVEL(ch) < 1 || GET_LEVEL(ch) >= LVL_IMMORT)))
+  if (!IS_NPC(ch) && ((GET_LEVEL(ch, LVL_TOTAL) < 1 || GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT)))
     return;
 
   if (IS_NPC(ch)) {
@@ -265,23 +263,22 @@ void gain_exp(struct char_data *ch, int 
   if (gain > 0) {
     gain = MIN(max_exp_gain, gain);	/* put a cap on the max gain per kill */
     GET_EXP(ch) += gain;
-    while (GET_LEVEL(ch) < LVL_IMMORT - immort_level_ok &&
-	GET_EXP(ch) >= level_exp(GET_CLASS(ch), GET_LEVEL(ch) + 1)) {
-      GET_LEVEL(ch) += 1;
+    while (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT - immort_level_ok &&
+	GET_EXP(ch) >= level_exp(GET_CLASS(ch), GET_LEVEL(ch, LVL_TOTAL) + 1)) {
+      GET_LEVEL(ch, LVL_TOTAL) += 1;
       num_levels++;
-      advance_level(ch);
       is_altered = TRUE;
     }
 
     if (is_altered) {
       mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s advanced %d level%s to level %d.",
-		GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch));
+		GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch, LVL_TOTAL));
       if (num_levels == 1)
         send_to_char(ch, "You rise a level!\r\n");
       else
 	send_to_char(ch, "You rise %d levels!\r\n", num_levels);
       set_title(ch, NULL);
-      if (GET_LEVEL(ch) >= LVL_IMMORT)
+      if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT)
         run_autowiz();
     }
   } else if (gain < 0) {
@@ -303,23 +300,22 @@ void gain_exp_regardless(struct char_dat
     GET_EXP(ch) = 0;
 
   if (!IS_NPC(ch)) {
-    while (GET_LEVEL(ch) < LVL_IMPL &&
-	GET_EXP(ch) >= level_exp(GET_CLASS(ch), GET_LEVEL(ch) + 1)) {
-      GET_LEVEL(ch) += 1;
+    while (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL &&
+	GET_EXP(ch) >= level_exp(GET_CLASS(ch), GET_LEVEL(ch, LVL_TOTAL) + 1)) {
+      GET_LEVEL(ch, LVL_TOTAL) += 1;
       num_levels++;
-      advance_level(ch);
       is_altered = TRUE;
     }
 
     if (is_altered) {
       mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s advanced %d level%s to level %d.",
-		GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch));
+		GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch, LVL_TOTAL));
       if (num_levels == 1)
         send_to_char(ch, "You rise a level!\r\n");
       else
 	send_to_char(ch, "You rise %d levels!\r\n", num_levels);
       set_title(ch, NULL);
-      if (GET_LEVEL(ch) >= LVL_IMMORT)
+      if (GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMMORT)
         run_autowiz();
     }
   }
@@ -433,7 +429,7 @@ void point_update(void)
     }
     if (!IS_NPC(i)) {
       update_char_objects(i);
-      if (GET_LEVEL(i) < idle_max_level)
+      if (GET_LEVEL(i, LVL_TOTAL) < idle_max_level)
 	check_idling(i);
     }
   }
diff -puN src/magic.c new/magic.c
--- src/magic.c	2002-11-22 21:35:44.000000000 +0100
+++ new/magic.c	2002-11-26 15:15:50.000000000 +0100
@@ -59,7 +59,7 @@ int mag_savingthrow(struct char_data *ch
   if (!IS_NPC(ch))
     class_sav = GET_CLASS(ch);
 
-  save = saving_throws(class_sav, type, GET_LEVEL(ch));
+  save = saving_throws(class_sav, type, GET_LEVEL(ch, LVL_TOTAL));
   save += GET_SAVE(ch, type);
   save += modifier;
 
@@ -101,7 +101,7 @@ void affect_update(void)
  *  mag_materials:
  *  Checks for up to 3 vnums (spell reagents) in the player's inventory.
  *
- * No spells implemented in Circle use mag_materials, but you can use
+ * No spells implemented in Circle 3.0 use mag_materials, but you can use
  * it to implement your own spells which require ingredients (i.e., some
  * heal spell which requires a rare herb or some such.)
  */
@@ -244,7 +244,7 @@ int mag_damage(int level, struct char_da
     break;
 
   case SPELL_ENERGY_DRAIN:
-    if (GET_LEVEL(victim) <= 2)
+    if (GET_LEVEL(victim, CLASS_MAGIC_USER) <= 2)
       dam = 100;
     else
       dam = dice(1, 10);
@@ -357,12 +357,12 @@ void mag_affects(int level, struct char_
     }
 
     af[0].location = APPLY_HITROLL;
-    af[0].duration = 1 + (GET_LEVEL(ch) / 2);
+    af[0].duration = 1 + (GET_LEVEL(ch, CLASS_MAGIC_USER) / 2);
     af[0].modifier = -1;
     af[0].bitvector = AFF_CURSE;
 
     af[1].location = APPLY_DAMROLL;
-    af[1].duration = 1 + (GET_LEVEL(ch) / 2);
+    af[1].duration = 1 + (GET_LEVEL(ch, CLASS_MAGIC_USER) / 2);
     af[1].modifier = -1;
     af[1].bitvector = AFF_CURSE;
 
@@ -405,7 +405,7 @@ void mag_affects(int level, struct char_
     if (!victim)
       victim = ch;
 
-    af[0].duration = 12 + (GET_LEVEL(ch) / 4);
+    af[0].duration = 12 + (GET_LEVEL(ch, LVL_TOTAL) / 4);
     af[0].modifier = -40;
     af[0].location = APPLY_AC;
     af[0].bitvector = AFF_INVISIBLE;
@@ -421,7 +421,7 @@ void mag_affects(int level, struct char_
     }
 
     af[0].location = APPLY_STR;
-    af[0].duration = GET_LEVEL(ch);
+    af[0].duration = GET_LEVEL(ch, LVL_TOTAL);
     af[0].modifier = -2;
     af[0].bitvector = AFF_POISON;
     to_vict = "You feel very sick.";
@@ -452,7 +452,7 @@ void mag_affects(int level, struct char_
     if (mag_savingthrow(victim, savetype, 0))
       return;
 
-    af[0].duration = 4 + (GET_LEVEL(ch) / 4);
+    af[0].duration = 4 + (GET_LEVEL(ch, LVL_TOTAL) / 4);
     af[0].bitvector = AFF_SLEEP;
 
     if (GET_POS(victim) > POS_SLEEPING) {
@@ -467,7 +467,7 @@ void mag_affects(int level, struct char_
       return;
 
     af[0].location = APPLY_STR;
-    af[0].duration = (GET_LEVEL(ch) / 2) + 4;
+    af[0].duration = (GET_LEVEL(ch, LVL_TOTAL) / 2) + 4;
     af[0].modifier = 1 + (level > 18);
     accum_duration = TRUE;
     accum_affect = TRUE;
@@ -476,7 +476,7 @@ void mag_affects(int level, struct char_
 
   case SPELL_SENSE_LIFE:
     to_vict = "Your feel your awareness improve.";
-    af[0].duration = GET_LEVEL(ch);
+    af[0].duration = GET_LEVEL(ch, LVL_TOTAL);
     af[0].bitvector = AFF_SENSE_LIFE;
     accum_duration = TRUE;
     break;
@@ -588,7 +588,7 @@ void mag_groups(int level, struct char_d
 /*
  * mass spells affect every creature in the room except the caster.
  *
- * No spells of this class currently implemented.
+ * No spells of this class currently implemented as of Circle 3.0.
  */
 void mag_masses(int level, struct char_data *ch, int spellnum, int savetype)
 {
@@ -650,7 +650,7 @@ void mag_areas(int level, struct char_da
 
     if (tch == ch)
       continue;
-    if (!IS_NPC(tch) && GET_LEVEL(tch) >= LVL_IMMORT)
+    if (!IS_NPC(tch) && GET_LEVEL(tch, LVL_TOTAL) >= LVL_IMMORT)
       continue;
     if (!pk_allowed && !IS_NPC(ch) && !IS_NPC(tch))
       continue;
@@ -666,7 +666,7 @@ void mag_areas(int level, struct char_da
 /*
  *  Every spell which summons/gates/conjours a mob comes through here.
  *
- *  None of these spells are currently implemented in CircleMUD; these
+ *  None of these spells are currently implemented in Circle 3.0; these
  *  were taken as examples from the JediMUD code.  Summons can be used
  *  for spells like clone, ariel servant, etc.
  *
@@ -883,7 +883,7 @@ void mag_alter_objs(int level, struct ch
   switch (spellnum) {
     case SPELL_BLESS:
       if (!OBJ_FLAGGED(obj, ITEM_BLESS) &&
-	  (GET_OBJ_WEIGHT(obj) <= 5 * GET_LEVEL(ch))) {
+	  (GET_OBJ_WEIGHT(obj) <= 5 * GET_LEVEL(ch, LVL_TOTAL))) {
 	SET_BIT(GET_OBJ_EXTRA(obj), ITEM_BLESS);
 	to_char = "$p glows briefly.";
       }
diff -puN src/mail.c new/mail.c
--- src/mail.c	2002-11-22 21:37:00.000000000 +0100
+++ new/mail.c	2002-11-13 17:26:02.000000000 +0100
@@ -529,7 +529,7 @@ void postmaster_send_mail(struct char_da
   long recipient;
   char buf[MAX_INPUT_LENGTH], **mailwrite;
 
-  if (GET_LEVEL(ch) < MIN_MAIL_LEVEL) {
+  if (GET_LEVEL(ch, LVL_TOTAL) < MIN_MAIL_LEVEL) {
     snprintf(buf, sizeof(buf), "$n tells you, 'Sorry, you have to be level %d to send mail!'", MIN_MAIL_LEVEL);
     act(buf, FALSE, mailman, 0, ch, TO_VICT);
     return;
diff -puN src/medit.c new/medit.c
--- src/medit.c	2002-11-22 21:35:44.000000000 +0100
+++ new/medit.c	2002-11-13 17:34:50.000000000 +0100
@@ -463,7 +463,7 @@ void medit_disp_menu(struct descriptor_d
 	  grn, nrm, yel, GET_SDESC(mob),
 	  grn, nrm, yel, GET_LDESC(mob),
 	  grn, nrm, yel, GET_DDESC(mob),
-	  grn, nrm, cyn, GET_LEVEL(mob), nrm,
+	  grn, nrm, cyn, GET_LEVEL(mob, LVL_TOTAL), nrm,
 	  grn, nrm, cyn, GET_ALIGNMENT(mob), nrm,
 	  grn, nrm, cyn, GET_HITROLL(mob), nrm,
 	  grn, nrm, cyn, GET_DAMROLL(mob), nrm,
@@ -922,7 +922,7 @@ void medit_parse(struct descriptor_data 
     break;
 
   case MEDIT_LEVEL:
-    GET_LEVEL(OLC_MOB(d)) = LIMIT(i, 1, 100);
+    GET_LEVEL(OLC_MOB(d), LVL_TOTAL) = LIMIT(i, 1, 100);
     break;
 
   case MEDIT_ALIGNMENT:
Common subdirectories: src/oasis and new/oasis
diff -puN src/oasis.c new/oasis.c
--- src/oasis.c	2002-11-22 21:35:44.000000000 +0100
+++ new/oasis.c	2002-11-13 17:35:20.000000000 +0100
@@ -131,7 +131,7 @@ ACMD(do_oasis)
 	send_to_char(ch, "Triggers save automatically.\r\n");
 	return;
       }
-    } else if (subcmd == SCMD_OASIS_ZEDIT && GET_LEVEL(ch) >= LVL_IMPL) {
+    } else if (subcmd == SCMD_OASIS_ZEDIT && GET_LEVEL(ch, LVL_TOTAL) >= LVL_IMPL) {
       if (str_cmp("new", buf1) || !buf3 || !*buf3)
 	send_to_char(ch, "Unknown command, perhaps 'new zone lower-room-number upper-room-number'?\r\n");
       else {
@@ -193,7 +193,8 @@ ACMD(do_oasis)
   /*
    * Everyone but IMPLs can only edit zones they have been assigned.
    */
-  if ( ( (zone_table[OLC_ZNUM(d)].number != GET_OLC_ZONE(ch) ) || (GET_OLC_ZONE(ch) < 1) ) && (GET_LEVEL(ch) < LVL_IMPL) ) {
+  if ( ( (zone_table[OLC_ZNUM(d)].number != GET_OLC_ZONE(ch) ) || (GET_OLC_ZONE(ch) < 1) ) && 
+	  (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMPL) ) {
     send_to_char(ch, "You do not have permission to edit this zone.\r\n");
     mudlog(BRF, LVL_IMPL, TRUE, "OLC: %s tried to edit zone %d allowed zone %d", GET_NAME(ch), zone_table[OLC_ZNUM(d)].number, GET_OLC_ZONE(ch));
     free(d->olc);
diff -puN src/oasis.h new/oasis.h
--- src/oasis.h	2002-11-22 21:35:44.000000000 +0100
+++ new/oasis.h	2002-11-17 13:50:56.000000000 +0100
@@ -34,10 +34,10 @@
  * Macros, defines, structs and globals for the OLC suite.  You will need
  * to adjust these numbers if you ever add more.
  */
-#define NUM_ROOM_FLAGS 		16
+#define NUM_ROOM_FLAGS 		20
 #define NUM_ROOM_SECTORS	10
 
-#define NUM_MOB_FLAGS		18
+#define NUM_MOB_FLAGS		20
 #define NUM_AFF_FLAGS		22
 #define NUM_ATTACK_TYPES	15
 
diff -puN src/objsave.c new/objsave.c
--- src/objsave.c	2002-05-02 05:12:42.000000000 +0200
+++ new/objsave.c	2002-11-13 17:26:30.000000000 +0100
@@ -605,7 +605,7 @@ int Crash_load(struct char_data *ch)
 
   /* Little hoarding check. -gg 3/1/98 */
   mudlog(NRM, MAX(GET_INVIS_LEV(ch), LVL_GOD), TRUE, "%s (level %d) has %d object%s (max %d).",
-	GET_NAME(ch), GET_LEVEL(ch), num_objs, num_objs != 1 ? "s" : "", max_obj_save);
+	GET_NAME(ch), GET_LEVEL(ch, LVL_TOTAL), num_objs, num_objs != 1 ? "s" : "", max_obj_save);
 
   /* turn this into a crash file by re-writing the control block */
   rent.rentcode = RENT_CRASH;
diff -puN src/oedit.c new/oedit.c
--- src/oedit.c	2002-11-22 21:35:44.000000000 +0100
+++ new/oedit.c	2002-11-13 17:35:54.000000000 +0100
@@ -994,7 +994,7 @@ void oedit_parse(struct descriptor_data 
       int counter;
 
       /* add in check here if already applied.. deny builders another */
-      if (GET_LEVEL(d->character) < LVL_IMPL) {
+      if (GET_LEVEL(d->character, LVL_TOTAL) < LVL_IMPL) {
         for (counter = 0; counter < MAX_OBJ_AFFECT; counter++) {
           if (OLC_OBJ(d)->affected[counter].location == number) {
             write_to_output(d, "Object already has that apply.");
diff -puN src/pfdefaults.h new/pfdefaults.h
--- src/pfdefaults.h	2002-11-22 21:37:00.000000000 +0100
+++ new/pfdefaults.h	2002-11-22 20:54:36.000000000 +0100
@@ -49,5 +49,6 @@
 #define PFDEF_HUNGER		0
 #define PFDEF_THIRST		0
 #define PFDEF_DRUNK		0
+#define PFDEF_JOINED    0
 
 #endif
diff -puN src/shop.h new/shop.h
--- src/shop.h	2002-11-13 20:49:28.000000000 +0100
+++ new/shop.h	2002-11-13 17:27:04.000000000 +0100
@@ -50,7 +50,7 @@ struct shop_data {
 
 
 /* Pretty general macros that could be used elsewhere */
-#define IS_GOD(ch)		(!IS_NPC(ch) && (GET_LEVEL(ch) >= LVL_GOD))
+#define IS_GOD(ch)		(!IS_NPC(ch) && (GET_LEVEL(ch, LVL_TOTAL) >= LVL_GOD))
 #define END_OF(buffer)		((buffer) + strlen((buffer)))
 
 
@@ -124,8 +124,8 @@ struct stack_data {
 
 
 
-#define WILL_START_FIGHT	(1 << 0)
-#define WILL_BANK_MONEY		(1 << 1)
+#define	WILL_START_FIGHT	1
+#define WILL_BANK_MONEY		2
 
 #define SHOP_KILL_CHARS(i)	(IS_SET(SHOP_BITVECTOR(i), WILL_START_FIGHT))
 #define SHOP_USES_BANK(i)	(IS_SET(SHOP_BITVECTOR(i), WILL_BANK_MONEY))
diff -puN src/spec_assign.c new/spec_assign.c
--- src/spec_assign.c	2001-12-04 13:22:54.000000000 +0100
+++ new/spec_assign.c	2002-11-16 17:55:36.000000000 +0100
@@ -28,7 +28,6 @@ SPECIAL(postmaster);
 SPECIAL(cityguard);
 SPECIAL(receptionist);
 SPECIAL(cryogenicist);
-SPECIAL(guild_guard);
 SPECIAL(guild);
 SPECIAL(puff);
 SPECIAL(fido);
@@ -38,7 +37,8 @@ SPECIAL(snake);
 SPECIAL(thief);
 SPECIAL(magic_user);
 SPECIAL(bank);
-SPECIAL(gen_board);
+SPECIAL(gen_board);
+SPECIAL(guildmaster);
 void assign_kings_castle(void);
 
 /* local functions */
@@ -50,6 +50,18 @@ void ASSIGNMOB(mob_vnum mob, SPECIAL(fna
 void ASSIGNOBJ(obj_vnum obj, SPECIAL(fname));
 
 /* functions to perform assignments */
+
+/* Only call this at boot up*/
+void assign_guilds(void)
+{
+  int i;
+   
+  for (i = 0; i <= top_of_world; i++)
+    if ((ROOM_FLAGGED(i, ROOM_GUILD_MAGE)) || (ROOM_FLAGGED(i, ROOM_GUILD_CLERIC)) 
+		|| (ROOM_FLAGGED(i, ROOM_GUILD_THIEF)) || (ROOM_FLAGGED(i, ROOM_GUILD_WARRIOR))) 
+	   ASSIGNROOM(GET_ROOM_VNUM(i), guildmaster);    
+}
+
 
 void ASSIGNMOB(mob_vnum mob, SPECIAL(fname))
 {
@@ -105,10 +117,6 @@ void assign_mobiles(void)
   ASSIGNMOB(3021, guild);
   ASSIGNMOB(3022, guild);
   ASSIGNMOB(3023, guild);
-  ASSIGNMOB(3024, guild_guard);
-  ASSIGNMOB(3025, guild_guard);
-  ASSIGNMOB(3026, guild_guard);
-  ASSIGNMOB(3027, guild_guard);
   ASSIGNMOB(3059, cityguard);
   ASSIGNMOB(3060, cityguard);
   ASSIGNMOB(3061, janitor);
@@ -211,7 +219,6 @@ void assign_mobiles(void)
 
   /* Desert */
   ASSIGNMOB(5004, magic_user);
-  ASSIGNMOB(5005, guild_guard); /* brass dragon */
   ASSIGNMOB(5010, magic_user);
   ASSIGNMOB(5014, magic_user);
 
diff -puN src/spec_procs.c new/spec_procs.c
--- src/spec_procs.c	2002-09-26 02:41:38.000000000 +0200
+++ new/spec_procs.c	2002-11-22 14:37:50.000000000 +0100
@@ -23,13 +23,13 @@
 /*   external vars  */
 extern struct time_info_data time_info;
 extern struct spell_info_type spell_info[];
-extern struct guild_info_type guild_info[];
 
 /* extern functions */
 ACMD(do_drop);
 ACMD(do_gen_door);
 ACMD(do_say);
 ACMD(do_action);
+ACMD(do_tell);
 
 /* local functions */
 void sort_spells(void);
@@ -82,7 +82,7 @@ const char *how_good(int percent)
   if (percent < 0)
     return " error)";
   if (percent == 0)
-    return " (not learned)";
+    return " (unpracticed)";
   if (percent <= 10)
     return " (awful)";
   if (percent <= 20)
@@ -122,7 +122,7 @@ extern int prac_params[4][NUM_CLASSES];
 void list_skills(struct char_data *ch)
 {
   const char *overflow = "\r\n**OVERFLOW**\r\n";
-  int i, sortpos, nlen;
+  int i, j, sortpos, nlen;
   size_t len = 0;
   char buf2[MAX_STRING_LENGTH];
 
@@ -137,11 +137,13 @@ void list_skills(struct char_data *ch)
   
   for (sortpos = 1; sortpos <= MAX_SKILLS; sortpos++) {
     i = spell_sort_info[sortpos];
-    if (GET_LEVEL(ch) >= spell_info[i].min_level[(int) GET_CLASS(ch)]) {
-      nlen = snprintf(buf2 + len, sizeof(buf2) - len, "%-20s %s\r\n", spell_info[i].name, how_good(GET_SKILL(ch, i)));
-      if (len + nlen >= sizeof(buf2) || nlen < 0)
-        break;
-      len += nlen;
+    for (j = 1; j < NUM_CLASSES; j++) {
+	  if(GET_LEVEL(ch, j) >= spell_info[i].min_level[j]) {
+        nlen = snprintf(buf2 + len, sizeof(buf2) - len, "%-20s %s\r\n", spell_info[i].name, how_good(GET_SKILL(ch, i)));
+        if (len + nlen >= sizeof(buf2) || nlen < 0)
+          break;
+        len += nlen;
+	  }
     }
   }
   if (len >= sizeof(buf2))
@@ -151,50 +153,6 @@ void list_skills(struct char_data *ch)
 }
 
 
-SPECIAL(guild)
-{
-  int skill_num, percent;
-
-  if (IS_NPC(ch) || !CMD_IS("practice"))
-    return (FALSE);
-
-  skip_spaces(&argument);
-
-  if (!*argument) {
-    list_skills(ch);
-    return (TRUE);
-  }
-  if (GET_PRACTICES(ch) <= 0) {
-    send_to_char(ch, "You do not seem to be able to practice now.\r\n");
-    return (TRUE);
-  }
-
-  skill_num = find_skill_num(argument);
-
-  if (skill_num < 1 ||
-      GET_LEVEL(ch) < spell_info[skill_num].min_level[(int) GET_CLASS(ch)]) {
-    send_to_char(ch, "You do not know of that %s.\r\n", SPLSKL(ch));
-    return (TRUE);
-  }
-  if (GET_SKILL(ch, skill_num) >= LEARNED(ch)) {
-    send_to_char(ch, "You are already learned in that area.\r\n");
-    return (TRUE);
-  }
-  send_to_char(ch, "You practice for a while...\r\n");
-  GET_PRACTICES(ch)--;
-
-  percent = GET_SKILL(ch, skill_num);
-  percent += MIN(MAXGAIN(ch), MAX(MINGAIN(ch), int_app[GET_INT(ch)].learn));
-
-  SET_SKILL(ch, skill_num, MIN(LEARNED(ch), percent));
-
-  if (GET_SKILL(ch, skill_num) >= LEARNED(ch))
-    send_to_char(ch, "You are now learned in that area.\r\n");
-
-  return (TRUE);
-}
-
-
 
 SPECIAL(dump)
 {
@@ -221,7 +179,7 @@ SPECIAL(dump)
     send_to_char(ch, "You are awarded for outstanding performance.\r\n");
     act("$n has been awarded for being a good citizen.", TRUE, ch, 0, 0, TO_ROOM);
 
-    if (GET_LEVEL(ch) < 3)
+    if (GET_LEVEL(ch, LVL_TOTAL) < 3)
       gain_exp(ch, value);
     else
       GET_GOLD(ch) += value;
@@ -335,12 +293,12 @@ void npc_steal(struct char_data *ch, str
 
   if (IS_NPC(victim))
     return;
-  if (GET_LEVEL(victim) >= LVL_IMMORT)
+  if (GET_LEVEL(victim, LVL_TOTAL) >= LVL_IMMORT)
     return;
   if (!CAN_SEE(ch, victim))
     return;
 
-  if (AWAKE(victim) && (rand_number(0, GET_LEVEL(ch)) == 0)) {
+  if (AWAKE(victim) && (rand_number(0, GET_LEVEL(ch, LVL_TOTAL)) == 0)) {
     act("You discover that $n has $s hands in your wallet.", FALSE, ch, 0, victim, TO_VICT);
     act("$n tries to steal gold from $N.", TRUE, ch, 0, victim, TO_NOTVICT);
   } else {
@@ -362,12 +320,12 @@ SPECIAL(snake)
   if (cmd || GET_POS(ch) != POS_FIGHTING || !FIGHTING(ch))
     return (FALSE);
 
-  if (IN_ROOM(FIGHTING(ch)) != IN_ROOM(ch) || rand_number(0, GET_LEVEL(ch)) != 0)
+  if (IN_ROOM(FIGHTING(ch)) != IN_ROOM(ch) || rand_number(0, GET_LEVEL(ch, LVL_TOTAL)) != 0)
     return (FALSE);
 
   act("$n bites $N!", 1, ch, 0, FIGHTING(ch), TO_NOTVICT);
   act("$n bites you!", 1, ch, 0, FIGHTING(ch), TO_VICT);
-  call_magic(ch, FIGHTING(ch), 0, SPELL_POISON, GET_LEVEL(ch), CAST_SPELL);
+  call_magic(ch, FIGHTING(ch), 0, SPELL_POISON, GET_LEVEL(ch, LVL_TOTAL), CAST_SPELL);
   return (TRUE);
 }
 
@@ -380,7 +338,7 @@ SPECIAL(thief)
     return (FALSE);
 
   for (cons = world[IN_ROOM(ch)].people; cons; cons = cons->next_in_room)
-    if (!IS_NPC(cons) && GET_LEVEL(cons) < LVL_IMMORT && !rand_number(0, 4)) {
+    if (!IS_NPC(cons) && GET_LEVEL(cons, LVL_TOTAL) < LVL_IMMORT && !rand_number(0, 4)) {
       npc_steal(ch, cons);
       return (TRUE);
     }
@@ -409,13 +367,13 @@ SPECIAL(magic_user)
   if (vict == NULL)
     return (TRUE);
 
-  if (GET_LEVEL(ch) > 13 && rand_number(0, 10) == 0)
+  if (GET_LEVEL(ch, LVL_TOTAL) > 13 && rand_number(0, 10) == 0)
     cast_spell(ch, vict, NULL, SPELL_POISON);
 
-  if (GET_LEVEL(ch) > 7 && rand_number(0, 8) == 0)
+  if (GET_LEVEL(ch, LVL_TOTAL) > 7 && rand_number(0, 8) == 0)
     cast_spell(ch, vict, NULL, SPELL_BLINDNESS);
 
-  if (GET_LEVEL(ch) > 12 && rand_number(0, 12) == 0) {
+  if (GET_LEVEL(ch, LVL_TOTAL) > 12 && rand_number(0, 12) == 0) {
     if (IS_EVIL(ch))
       cast_spell(ch, vict, NULL, SPELL_ENERGY_DRAIN);
     else if (IS_GOOD(ch))
@@ -425,7 +383,7 @@ SPECIAL(magic_user)
   if (rand_number(0, 4))
     return (TRUE);
 
-  switch (GET_LEVEL(ch)) {
+  switch (GET_LEVEL(ch, LVL_TOTAL)) {
   case 4:
   case 5:
     cast_spell(ch, vict, NULL, SPELL_MAGIC_MISSILE);
@@ -464,39 +422,7 @@ SPECIAL(magic_user)
 /* ********************************************************************
 *  Special procedures for mobiles                                      *
 ******************************************************************** */
-
-SPECIAL(guild_guard)
-{
-  int i;
-  struct char_data *guard = (struct char_data *)me;
-  const char *buf = "The guard humiliates you, and blocks your way.\r\n";
-  const char *buf2 = "The guard humiliates $n, and blocks $s way.";
-
-  if (!IS_MOVE(cmd) || AFF_FLAGGED(guard, AFF_BLIND))
-    return (FALSE);
-
-  if (GET_LEVEL(ch) >= LVL_IMMORT)
-    return (FALSE);
-
-  for (i = 0; guild_info[i].guild_room != NOWHERE; i++) {
-    /* Wrong guild or not trying to enter. */
-    if (GET_ROOM_VNUM(IN_ROOM(ch)) != guild_info[i].guild_room || cmd != guild_info[i].direction)
-      continue;
-
-    /* Allow the people of the guild through. */
-    if (!IS_NPC(ch) && GET_CLASS(ch) == guild_info[i].pc_class)
-      continue;
-
-    send_to_char(ch, "%s", buf);
-    act(buf2, FALSE, ch, 0, 0, TO_ROOM);
-    return (TRUE);
-  }
-
-  return (FALSE);
-}
-
-
-
+
 SPECIAL(puff)
 {
   char actbuf[MAX_INPUT_LENGTH];
@@ -639,7 +565,7 @@ SPECIAL(cityguard)
 }
 
 
-#define PET_PRICE(pet) (GET_LEVEL(pet) * 300)
+#define PET_PRICE(pet) (GET_LEVEL(pet, LVL_TOTAL) * 300)
 
 SPECIAL(pet_shops)
 {
@@ -703,8 +629,133 @@ SPECIAL(pet_shops)
   /* All commands except list and buy */
   return (FALSE);
 }
-
-
+
+
+
+
+SPECIAL(guildmaster) 
+{                 
+  struct char_data *tch, *gm = NULL;
+  char buf[MAX_STRING_LENGTH];
+  int class, join = FALSE;
+
+  if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_GUILD_MAGE)) class = CLASS_MAGIC_USER;
+  else if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_GUILD_CLERIC)) class = CLASS_CLERIC;
+  else if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_GUILD_THIEF)) class = CLASS_THIEF;
+  else if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_GUILD_WARRIOR)) class = CLASS_WARRIOR;
+  else return (FALSE);
+
+  if (IS_NPC(ch) || (!CMD_IS("promote") && !CMD_IS("join")))
+    return (FALSE);
+
+  if (CMD_IS("join"))
+	join = TRUE;
+
+  for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) {
+    if (!CAN_SEE(ch, tch))
+      continue;
+	  
+	if (IS_NPC(tch) && MOB_FLAGGED(tch, MOB_GUILDMASTER)) {
+      gm = tch;
+	}
+
+	continue;
+  }
+
+
+  if(!gm || (!CAN_SEE(ch, gm))) {
+	send_to_char(ch, "Do you see a guildmaster here?\r\n");
+	return (TRUE);
+  }
+
+  skip_spaces(&argument);
+
+  if ((PLR_FLAGGED(ch, PLR_KILLER) || PLR_FLAGGED(ch, PLR_THIEF)) && (class != CLASS_THIEF)) {
+    snprintf(buf, sizeof(buf), "%s %s", GET_NAME(ch), "We won't give our services to murderers or thieves!");
+    do_tell(gm, buf, find_command("tell"), 0);
+  } else if ((join) && (class == GET_CLASS(ch))) {
+    snprintf(buf, sizeof(buf), "%s %s", GET_NAME(ch), "But you are already part of this guild!");
+    do_tell(gm, buf, find_command("tell"), 0);
+	return (TRUE);
+  } else if ((join) && (GET_JOINED(ch) <= 5)) {
+    snprintf(buf, sizeof(buf), "%s %s", GET_NAME(ch), "Sorry, there is a minimum amount of levels you will have to spend in your current guild.");
+    do_tell(gm, buf, find_command("tell"), 0);
+    return (TRUE);
+  } else if ((join) && (GET_CLASS(ch) != class) && (GET_CLASS(ch) != CLASS_EXPLORER)) {
+	snprintf(buf, sizeof(buf), "%s Very well, we're glad to have you in our %s guild! I've also reported to the %s guild that you no longer are a member of them.", GET_NAME(ch), pc_class_types[class], pc_class_types[GET_CLASS(ch)]);
+    do_tell(gm, buf, find_command("tell"), 0);
+	mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s left the %s Guild, and joined the %s guild.", GET_NAME(ch), 
+	    pc_class_types[GET_CLASS(ch)], pc_class_types[class]);
+	GET_JOINED(ch) = 0;
+	GET_CLASS(ch) = class;
+	return (TRUE);
+  } else if ((GET_LEVEL(ch, LVL_TOTAL)) == (GET_LEVEL(ch, CLASS_MAGIC_USER)) + (GET_LEVEL(ch, CLASS_CLERIC))
+	  + (GET_LEVEL(ch, CLASS_THIEF)) + (GET_LEVEL(ch, CLASS_WARRIOR))) {
+	snprintf(buf, sizeof(buf), "%s %s", GET_NAME(ch), "Sorry, but you don't seem ready yet to be promoted.");
+    do_tell(gm, buf, find_command("tell"), 0);
+    return (TRUE);
+  } else if (GET_CLASS(ch) != class) {
+	snprintf(buf, sizeof(buf), "%s %s", GET_NAME(ch), "You aren't in the right guild to be promoted!");
+    do_tell(gm, buf, find_command("tell"), 0);
+    return (TRUE);
+  }
+
+  GET_LEVEL(ch, class) += 1;
+  GET_JOINED(ch)++;
+  advance_level(ch);
+ 
+  snprintf(buf, sizeof(buf), "%s Congratulations! You've been promoted in the %s Guild!", GET_NAME(ch), pc_class_types[class]);
+  do_tell(gm, buf, find_command("tell"), 0);
+ 
+  mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s is promoted to level %d at %s. (Total lvl:%d)", GET_NAME(ch), 
+     GET_LEVEL(ch, class), pc_class_types[GET_CLASS(ch)], GET_LEVEL(ch, LVL_TOTAL));
+
+  return (TRUE);
+}
+
+SPECIAL(guild)
+{
+  int skill_num, percent;
+
+  if (IS_NPC(ch) || !CMD_IS("practice"))
+    return (FALSE);
+
+  skip_spaces(&argument);
+
+  if (!*argument) {
+    list_skills(ch);
+    return (TRUE);
+  }
+  if (GET_PRACTICES(ch) <= 0) {
+    send_to_char(ch, "You do not seem to be able to practice now.\r\n");
+    return (TRUE);
+  }
+
+  skill_num = find_skill_num(argument);
+
+  if (skill_num < 1 ||
+      GET_LEVEL(ch, LVL_TOTAL) < spell_info[skill_num].min_level[(int) GET_CLASS(ch)]) {
+    send_to_char(ch, "You do not know of that %s.\r\n", SPLSKL(ch));
+    return (TRUE);
+  }
+  if (GET_SKILL(ch, skill_num) >= LEARNED(ch)) {
+    send_to_char(ch, "You are already learned in that area.\r\n");
+    return (TRUE);
+  }
+  send_to_char(ch, "You practice for a while...\r\n");
+  GET_PRACTICES(ch)--;
+
+  percent = GET_SKILL(ch, skill_num);
+  percent += MIN(MAXGAIN(ch), MAX(MINGAIN(ch), int_app[GET_INT(ch)].learn));
+
+  SET_SKILL(ch, skill_num, MIN(LEARNED(ch), percent));
+
+  if (GET_SKILL(ch, skill_num) >= LEARNED(ch))
+    send_to_char(ch, "You are now learned in that area.\r\n");
+
+  return (TRUE);
+}
+
 
 /* ********************************************************************
 *  Special procedures for objects                                     *
diff -puN src/spell_parser.c new/spell_parser.c
--- src/spell_parser.c	2002-11-22 21:35:44.000000000 +0100
+++ new/spell_parser.c	2002-11-22 14:28:16.000000000 +0100
@@ -34,6 +34,7 @@ int mag_manacost(struct char_data *ch, i
 ACMD(do_cast);
 void unused_spell(int spl);
 void mag_assign_spells(void);
+int sameclass(struct char_data *ch, struct char_data *tch);
 
 /*
  * This arrangement is pretty stupid, but the number of skills is limited by
@@ -88,7 +89,7 @@ const char *unused_spellname = "!UNUSED!
 int mag_manacost(struct char_data *ch, int spellnum)
 {
   return MAX(SINFO.mana_max - (SINFO.mana_change *
-		    (GET_LEVEL(ch) - SINFO.min_level[(int) GET_CLASS(ch)])),
+		    (GET_LEVEL(ch, LVL_TOTAL) - SINFO.min_level[(int) GET_CLASS(ch)])),
 	     SINFO.mana_min);
 }
 
@@ -97,7 +98,7 @@ void say_spell(struct char_data *ch, int
 	            struct obj_data *tobj)
 {
   char lbuf[256], buf[256], buf1[256], buf2[256];	/* FIXME */
-  const char *format;
+  const char *format, *format2;
 
   struct char_data *i;
   int j, ofs = 0;
@@ -121,15 +122,21 @@ void say_spell(struct char_data *ch, int
   }
 
   if (tch != NULL && IN_ROOM(tch) == IN_ROOM(ch)) {
-    if (tch == ch)
+	if (tch == ch) {
       format = "$n closes $s eyes and utters the words, '%s'.";
-    else
-      format = "$n stares at $N and utters the words, '%s'.";
+	  format2 = "You close your eyes and utter the words, '%s'.";
+	} else {
+      format = "$n stares at $N and utters the words, '%s'.";
+	  format2 = "You stare at $N and utter the words, '%s'.";
+	}
   } else if (tobj != NULL &&
-	     ((IN_ROOM(tobj) == IN_ROOM(ch)) || (tobj->carried_by == ch)))
-    format = "$n stares at $p and utters the words, '%s'.";
-  else
+	     ((IN_ROOM(tobj) == IN_ROOM(ch)) || (tobj->carried_by == ch))) {
+    format = "$n stares at $p and utters the words, '%s'.";
+    format2 = "You stare at $p and utter the words, '%s'.";
+  } else {
     format = "$n utters the words, '%s'.";
+    format2 = "You utter the words, '%s'.";
+  }
 
   snprintf(buf1, sizeof(buf1), format, skill_name(spellnum));
   snprintf(buf2, sizeof(buf2), format, buf);
@@ -137,7 +144,7 @@ void say_spell(struct char_data *ch, int
   for (i = world[IN_ROOM(ch)].people; i; i = i->next_in_room) {
     if (i == ch || i == tch || !i->desc || !AWAKE(i))
       continue;
-    if (GET_CLASS(ch) == GET_CLASS(i))
+    if (sameclass(ch, i))
       perform_act(buf1, ch, tobj, tch, i);
     else
       perform_act(buf2, ch, tobj, tch, i);
@@ -145,10 +152,33 @@ void say_spell(struct char_data *ch, int
 
   if (tch != NULL && tch != ch && IN_ROOM(tch) == IN_ROOM(ch)) {
     snprintf(buf1, sizeof(buf1), "$n stares at you and utters the words, '%s'.",
-	    GET_CLASS(ch) == GET_CLASS(tch) ? skill_name(spellnum) : buf);
+	    sameclass(ch, tch) ? skill_name(spellnum) : buf);
     act(buf1, FALSE, ch, NULL, tch, TO_VICT);
-  }
-}
+  }
+  
+  snprintf(buf1, sizeof(buf1), format2, skill_name(spellnum));
+  act(buf1, FALSE, ch, NULL, tch, TO_CHAR);
+}
+
+int sameclass(struct char_data *ch, struct char_data *tch)
+{
+  int i;
+
+  for (i = 1; i < NUM_CLASSES-1; i++) {
+    if (IS_MAGIC_USER(ch) && IS_MAGIC_USER(tch))
+      return (TRUE);
+    if (IS_CLERIC(ch) && IS_CLERIC(tch))
+      return (TRUE);
+    if (IS_THIEF(ch) && IS_THIEF(tch))
+      return (TRUE);
+    if (IS_WARRIOR(ch) && IS_WARRIOR(tch))
+      return (TRUE);
+  }
+
+  return (FALSE);
+}
+
+
 
 /*
  * This function should be used anytime you are not 100% sure that you have
@@ -501,10 +531,9 @@ int cast_spell(struct char_data *ch, str
     send_to_char(ch, "You can't cast this spell if you're not in a group!\r\n");
     return (0);
   }
-  send_to_char(ch, "%s", OK);
   say_spell(ch, spellnum, tch, tobj);
 
-  return (call_magic(ch, tch, tobj, spellnum, GET_LEVEL(ch), CAST_SPELL));
+  return (call_magic(ch, tch, tobj, spellnum, (GET_LEVEL(ch, CLASS_MAGIC_USER) + GET_LEVEL(ch, CLASS_CLERIC)), CAST_SPELL));
 }
 
 
@@ -519,7 +548,7 @@ ACMD(do_cast)
   struct char_data *tch = NULL;
   struct obj_data *tobj = NULL;
   char *s, *t;
-  int mana, spellnum, i, target = 0;
+  int mana, spellnum, i, target = 0, cast = FALSE;
 
   if (IS_NPC(ch))
     return;
@@ -544,11 +573,15 @@ ACMD(do_cast)
   if ((spellnum < 1) || (spellnum > MAX_SPELLS)) {
     send_to_char(ch, "Cast what?!?\r\n");
     return;
-  }
-  if (GET_LEVEL(ch) < SINFO.min_level[(int) GET_CLASS(ch)]) {
+  }
+  for (i = 1; i < NUM_CLASSES; i++) 
+    if(GET_LEVEL(ch, i) < SINFO.min_level[i])
+      cast = TRUE;
+  
+  if(!cast) {
     send_to_char(ch, "You do not know that spell!\r\n");
     return;
-  }
+  }
   if (GET_SKILL(ch, spellnum) == 0) {
     send_to_char(ch, "You are unfamiliar with that spell.\r\n");
     return;
@@ -624,7 +657,7 @@ ACMD(do_cast)
     return;
   }
   mana = mag_manacost(ch, spellnum);
-  if ((mana > 0) && (GET_MANA(ch) < mana) && (GET_LEVEL(ch) < LVL_IMMORT)) {
+  if ((mana > 0) && (GET_MANA(ch) < mana) && (GET_LEVEL(ch, LVL_TOTAL) < LVL_IMMORT)) {
     send_to_char(ch, "You haven't the energy to cast that spell!\r\n");
     return;
   }
diff -puN src/spells.c new/spells.c
--- src/spells.c	2002-11-22 21:35:44.000000000 +0100
+++ new/spells.c	2002-11-13 17:33:04.000000000 +0100
@@ -114,7 +114,7 @@ ASPELL(spell_summon)
   if (ch == NULL || victim == NULL)
     return;
 
-  if (GET_LEVEL(victim) > MIN(LVL_IMMORT - 1, level + 3)) {
+  if (GET_LEVEL(victim, LVL_TOTAL) > MIN(LVL_IMMORT - 1, level + 3)) {
     send_to_char(ch, "%s", SUMMON_FAIL);
     return;
   }
@@ -221,7 +221,7 @@ ASPELL(spell_charm)
     send_to_char(ch, "Your victim resists!\r\n");
   else if (AFF_FLAGGED(ch, AFF_CHARM))
     send_to_char(ch, "You can't have any followers of your own!\r\n");
-  else if (AFF_FLAGGED(victim, AFF_CHARM) || level < GET_LEVEL(victim))
+  else if (AFF_FLAGGED(victim, AFF_CHARM) || level < GET_LEVEL(victim, LVL_TOTAL))
     send_to_char(ch, "You fail.\r\n");
   /* player charming another player - no legal reason for this */
   else if (!pk_allowed && !IS_NPC(victim))
@@ -334,7 +334,7 @@ ASPELL(spell_identify)
 	      GET_NAME(victim), age(victim)->year, age(victim)->month,
 	      age(victim)->day, age(victim)->hours);
     send_to_char(ch, "Height %d cm, Weight %d pounds\r\n", GET_HEIGHT(victim), GET_WEIGHT(victim));
-    send_to_char(ch, "Level: %d, Hits: %d, Mana: %d\r\n", GET_LEVEL(victim), GET_HIT(victim), GET_MANA(victim));
+    send_to_char(ch, "Level: %d, Hits: %d, Mana: %d\r\n", GET_LEVEL(victim, LVL_TOTAL), GET_HIT(victim), GET_MANA(victim));
     send_to_char(ch, "AC: %d, Hitroll: %d, Damroll: %d\r\n", compute_armor_class(victim), GET_HITROLL(victim), GET_DAMROLL(victim));
     send_to_char(ch, "Str: %d/%d, Int: %d, Wis: %d, Dex: %d, Con: %d, Cha: %d\r\n",
 	GET_STR(victim), GET_ADD(victim), GET_INT(victim),
diff -puN src/structs.h new/structs.h
--- src/structs.h	2002-11-22 21:37:00.000000000 +0100
+++ new/structs.h	2002-11-19 16:34:36.000000000 +0100
@@ -17,14 +17,14 @@
  * You are supposed to compare this with the macro CIRCLEMUD_VERSION()
  * in utils.h.  See there for usage.
  */
-#define _CIRCLEMUD	0x030100 /* Major/Minor/Patchlevel - MMmmPP */
+#define _CIRCLEMUD	0x030016 /* Major/Minor/Patchlevel - MMmmPP */
 
 /*
  * If you want equipment to be automatically equipped to the same place
  * it was when players rented, set the define below to 1.  Please note
  * that this will require erasing or converting all of your rent files.
  * And of course, you have to recompile everything.  We need this feature
- * for CircleMUD to be complete but we refuse to break binary file
+ * for CircleMUD 3.0 to be complete but we refuse to break binary file
  * compatibility.
  */
 #define USE_AUTOEQ	0	/* TRUE/FALSE aren't defined yet. */
@@ -88,8 +88,12 @@
 #define ROOM_ATRIUM		(1 << 13)  /* (R) The door to a house	*/
 #define ROOM_OLC		(1 << 14)  /* (R) Modifyable/!compress	*/
 #define ROOM_BFS_MARK		(1 << 15)  /* (R) breath-first srch mrk	*/
+#define ROOM_GUILD_MAGE		(1 << 16)  /* Guild Room		*/
+#define ROOM_GUILD_CLERIC	(1 << 17)  /* Guild Room		*/
+#define ROOM_GUILD_THIEF	(1 << 18)  /* Guild Room		*/
+#define ROOM_GUILD_WARRIOR	(1 << 19)  /* Guild Room		*/
 
-
+
 /* Exit info: used in room_data.dir_option.exit_info */
 #define EX_ISDOOR		(1 << 0)   /* Exit is a door		*/
 #define EX_CLOSED		(1 << 1)   /* The door is closed	*/
@@ -112,15 +116,18 @@
 
 /* char and mob-related defines *****************************************/
 
+
 
 /* PC classes */
-#define CLASS_UNDEFINED	  (-1)
-#define CLASS_MAGIC_USER  0
-#define CLASS_CLERIC      1
-#define CLASS_THIEF       2
-#define CLASS_WARRIOR     3
+#define CLASS_UNDEFINED	  (-1)
+#define LVL_TOTAL         0 /* This is the total of all levels added up */
+#define CLASS_EXPLORER    1 /* Player will start with this flag */
+#define CLASS_MAGIC_USER  2
+#define CLASS_CLERIC      3
+#define CLASS_THIEF       4
+#define CLASS_WARRIOR     5
 
-#define NUM_CLASSES	  4  /* This must be the number of classes!! */
+#define NUM_CLASSES	  6  /* This must be the number of classes!! */
 
 /* NPC classes (currently unused - feel free to implement!) */
 #define CLASS_OTHER       0
@@ -189,7 +196,7 @@
 #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_NOTDEADYET   (1 << 18) /* (R) Mob being extracted.		*/
-
+#define MOB_GUILDMASTER  (1 << 19) 
 
 /* Preference flags: used by char_data.player_specials.pref */
 #define PRF_BRIEF       (1 << 0)  /* Room descs won't normally be shown	*/
@@ -753,14 +760,16 @@ struct pclean_criteria_data {
 /* general player-related info, usually PC's and NPC's */
 struct char_player_data {
    char	passwd[MAX_PWD_LENGTH+1]; /* character's password      */
-   char	*name;	       /* PC / NPC s name (kill ...  )         */
-   char	*short_descr;  /* for NPC 'actions'                    */
-   char	*long_descr;   /* for 'look'			       */
-   char	*description;  /* Extra descriptions                   */
-   char	*title;        /* PC / NPC's title                     */
+   char	*name;	       /* NPC's title                     */
    byte sex;           /* PC / NPC's sex                       */
-   byte chclass;       /* PC / NPC's class		       */
-   byte level;         /* PC / NPC's level                     */
+   byte level[NUM_CLASSES+1];    /* PC / NPC s name (kill ...  )         */
+   int joinedlevels;
+   byte currentclass;
+   char	*short_descr;  /* for NPC 'actions'                    */
+   char	*long_descr;   /* for 'look'			       */
+   char	*description;  /* Extra descriptions                   */
+   char	*title;        /* PC /