area_current/castle/
area_current/gahld/
clans/
player/
player/c/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  MrMud improvements (C) 1993, 1994 by Douglas Michael & David Bills.    *
 *                                                                         *
 ***************************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "merc.h"

/* costs are in thousands of dollars */
#define COST_OF_ENTRANCE 30000
#define COST_OF_ROOM     20000
#define COST_OF_DOOR      4000
#define COST_OF_BACKDOOR 70000
#define COST_OF_STAT        10
#define COST_OF_SET       1000
#define COST_OF_CREATE   15000

bool castle_needs_saving=FALSE;

/* return name of bits that are set */
char *broken_bits( int , char * , bool );
char *justify( char *);

extern int top_mob_index;
extern int top_reset;

/*
 * get_bitvector_value: either sets number to the value represented in name,
 *   or it searches the bitvector list for a matching name and sets number to
 *   that bitvector's value--in either case it returns TRUE.  Otherwise, it
 *   returns FALSE.  If the string allowed is not NULL, then it limits the 
 *   values searched to those staring with the allowed string.  Also doesn't
 *   accept numbers if allowed is not NULL.
 */
bool get_bitvector_value(char *name,int *number,char *allowed)
{
  int cnt;

  if(allowed==NULL && is_number(name))
      {
      *number=atol(name);
      return TRUE;
      }
  if(is_name_short(allowed,name))
    for( cnt=0; cnt < MAX_BITVECTOR; cnt++)
      if( is_name( name, bitvector_table[cnt].name ))
        {
        *number=bitvector_table[cnt].value;
        return TRUE;
        }
  *number=-1;
  return FALSE;
}

void list_bitvectors(CHAR_DATA *ch,char *prefix)
{
  int cnt;
  char buf[81],bigBuf[MAX_STRING_LENGTH];
  
  bigBuf[0]='\0';
  for( cnt=0; cnt < MAX_BITVECTOR; cnt++)
    if( is_name_short( prefix, bitvector_table[cnt].name ))
      {
      sprintf(buf,"   %s\n\r",bitvector_table[cnt].name);
      strcat(bigBuf,buf);
      }
  if(bigBuf[0]=='\0')
    {
    sprintf(buf,"There are no bitvectors starting with '%s'.\n\r",prefix);
    send_to_char(buf,ch);
    return;
    }
  send_to_char(bigBuf,ch);
  return;
}

bool do_castle_mstat( CHAR_DATA *ch, char *argument )
  {
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_INPUT_LENGTH];
  AFFECT_DATA *paf;
  CHAR_DATA *victim;
  OBJ_DATA *wield;
  sh_int numDice,sizeDice;
  MPROG_DATA *mprg;



  one_argument( argument, arg );

  if ( arg[0] == '\0' )
    {
    send_to_char( "Mstat whom?\n\r", ch );
    return FALSE;
    }

  if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
    send_to_char( "They aren't here.\n\r", ch );
    return FALSE;
    }

  if(!IS_NPC(victim))
    {
    send_to_char( "Don't be silly.\n\r", ch );
    return FALSE;
    }

  if ( victim->pIndexData->creator_pvnum!=ch->pcdata->pvnum )
    {
    send_to_char( "You can't stat them!\n\r", ch );
    return FALSE;
    }

  sprintf( buf, "Name: %s.\n\r", victim->name );
  send_to_char( buf, ch );
  sprintf( buf, "Short description: %s\n\rLong  description: %s",
           victim->short_descr,
           victim->long_descr[0] != '\0' ? victim->long_descr : "(none).\n\r" );
  send_to_char( buf, ch );

  sprintf( buf, "Description: %s\n\r", victim->description);
  send_to_char( buf, ch );


  sprintf( buf, "Sex: %s.  Room: %u.  Race: %s.\n\r",
           victim->sex == SEX_MALE    ? "male"   :
           victim->sex == SEX_FEMALE  ? "female" : "neutral",
           victim->in_room == NULL    ?        0 : victim->in_room->vnum,
           race_table[victim->race].race_name);
  send_to_char( buf, ch );

  sprintf( buf, "Str: %d.  Int: %d.  Wis: %d.  Dex: %d.  Con: %d.\n\r",
           get_curr_str(victim),
           get_curr_int(victim),
           get_curr_wis(victim),
           get_curr_dex(victim),
           get_curr_con(victim) );
  send_to_char( buf, ch );

  sprintf( buf, "Hp: %d/%d.  Mana: %d/%d.  Move: %d/%d.\n\r",
           victim->hit,         victim->max_hit,
           victim->mana,        victim->max_mana,
           victim->move,        victim->max_move);
  send_to_char( buf, ch );
 
  sprintf( buf, "Lv: %d.  Class: %d.  Align: %d.  AC: %d.\n\r",
          victim->level,   victim->class, victim->alignment, 
           98-mob_armor(victim)+victim->npcdata->armor/3-victim->level*4);
  send_to_char( buf, ch );

  /* dice indicator added by Dug 10/2/93 */
  wield = get_eq_char( victim, WEAR_WIELD );
  if((wield!=NULL)&&wield->item_type!=ITEM_WEAPON)
    wield=NULL;
  numDice=(wield!=NULL)?wield->value[1]:(IS_NPC(victim)?victim->npcdata->damnodice:1);
  sizeDice=(wield!=NULL)?wield->value[2]:(IS_NPC(victim)?victim->npcdata->damsizedice:4+victim->level/4);
  sprintf( buf, "Hitroll: %d.  Damroll: (%dd%d)+%d.  Position: %d.  Wimpy: %d.\n\r", GET_HITROLL(victim), numDice, sizeDice,victim->npcdata->damplus+GET_DAMROLL(victim), victim->position, victim->wimpy);
  send_to_char( buf, ch );

  sprintf( buf, "Fighting: %s.\n\r",
           victim->fighting ? victim->fighting->who->name : "(none)" );
  send_to_char( buf, ch );

  sprintf( buf, "Carry number: %d.  Carry weight: %d.\n\r",
           victim->carry_number, victim->carry_weight );
  send_to_char( buf, ch );

  sprintf( buf, "Timer: %d.  Act: %s.\n\r", victim->timer,
           broken_bits(victim->act, "CACT_", FALSE));
  send_to_char( buf, ch );

  sprintf( buf, "Master: %s.  Leader: %s.  Affected by: %s.\n\r",
           victim->master      ? victim->master->name   : "(none)",
           victim->leader      ? victim->leader->name   : "(none)",
           affect_bit_name( victim->affected_by ) );
  send_to_char( buf, ch );

  /* added shot_timer and shot_aware entries -dug */
  sprintf(buf,"Basic Armor: %d  Current Armor: %d\n\r",
          victim->npcdata->armor, mob_armor(victim) );
  send_to_char(buf,ch);

  for ( paf = victim->first_affect; paf != NULL; paf = paf->next )
    {
    sprintf(buf,"Spell: '%s' modifies %s by %d for %d hours with bits %s.\n\r",
            skill_table[(int) paf->type].name,
            affect_loc_name( paf->location ),
            paf->modifier,
            paf->duration,
            affect_bit_name( paf->bitvector ));
    send_to_char( buf, ch );
    }
   
  if(IS_SET( victim->pIndexData->act, ACT_BODY))
    {
    int cnt;
    strcpy(buf, "Body parts: ");
    for( cnt=0; cnt<MAX_BODY; cnt++)
    if( IS_SET( victim->pIndexData->body_parts, 1<<cnt))
      {
      strcat( buf, body_table[cnt].name);
      strcat( buf, " ");
      }
    strcat( buf, "\n\r");
    strcat(buf, "Attack parts: ");
    for( cnt=0; cnt<MAX_BODY; cnt++)
      if( IS_SET( victim->pIndexData->attack_parts, 1<<cnt))
        {
        strcat( buf, body_table[cnt].name);
        strcat( buf, " ");
        }
    strcat( buf, "\n\r");
    send_to_char( buf, ch );
    }
    
  if ( !( victim->pIndexData->progtypes ) )
    {
    send_to_char( "That Mobile has no Programs set.\n\r", ch);
    return TRUE;
    }

  for ( mprg = victim->pIndexData->mobprogs; mprg != NULL; mprg = mprg->next )
    {
    sprintf( buf, ">%s %s\n\r%s\n\r", 
             mprog_type_to_name( mprg->type ),
             mprg->arglist, mprg->comlist );
    send_to_char( buf, ch );
    }

  return TRUE;
  }

bool do_castle_ostat( CHAR_DATA *ch, char *argument )
  {
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_INPUT_LENGTH];
  AFFECT_DATA *paf;
  OBJ_DATA *obj;

  one_argument( argument, arg );

  if ( arg[0] == '\0' )
    {
    send_to_char( "Ostat what?\n\r", ch );
    return FALSE;
    }

  if(is_number(arg))
    {
    int anum;

    anum=atol(arg);
    for(obj=first_object;obj!=NULL;obj=obj->next)
      if(obj->pIndexData!=NULL&&obj->pIndexData->vnum==anum)
        break;
    if(obj==NULL)
      {
      send_to_char( "No object loaded has that vnum.\n\r", ch );
      return FALSE;
      }
    }
  else
    {
    if ( ( obj = get_obj_world( ch, arg ) ) == NULL )
      {
      send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
      return FALSE;
      }
    }

  if ( obj->pIndexData->creator_pvnum!=ch->pcdata->pvnum )
    {
    send_to_char( "You can't stat that!\n\r", ch );
    return FALSE;
    }

  sprintf( buf, "Name: %s.", obj->name );
  send_to_char( buf, ch );

  sprintf( buf, "Type: %s.  Level: %d.\n\r", item_type_name( obj ),
           obj->level );
  send_to_char( buf, ch );

  sprintf( buf, "Short description: %s.\n\rLong description: %s\n\r",
           obj->short_descr, obj->description );
  send_to_char( buf, ch );

  sprintf( buf, "Wear bits: %d.  Extra bits: %s.\n\r",
           obj->wear_flags, extra_bit_name( obj->extra_flags ) );
  send_to_char( buf, ch );

  sprintf( buf, "Weight: %d/%d.\n\r", obj->weight, get_obj_weight( obj ) );
  send_to_char( buf, ch );

  sprintf( buf, "Values: %d %d %d %d.\n\r",
           obj->value[0], obj->value[1], obj->value[2], obj->value[3] );
  send_to_char( buf, ch );

  if ( obj->first_extradesc != NULL || obj->pIndexData->first_extradesc != NULL )
    {
    EXTRA_DESCR_DATA *ed;

    strcpy( buf, "Extra description keywords: '" );

    for ( ed = obj->first_extradesc; ed != NULL; ed = ed->next )
      {
      strcat( buf, ed->keyword );
      if ( ed->next != NULL )
        strcat( buf, " " );
      }

    for ( ed = obj->pIndexData->first_extradesc; ed != NULL; ed = ed->next )
      {
      strcat( buf, ed->keyword );
      if ( ed->next != NULL )
        strcat( buf, " " );
      }
    strcat( buf, "'.\n\r" );
    send_to_char( buf, ch);
    }

  for ( paf = obj->first_affect; paf != NULL; paf = paf->next )
    {
    sprintf( buf, "Affects %s by %d.\n\r",
             affect_loc_name( paf->location ), paf->modifier );
    send_to_char( buf, ch );
    }

  for ( paf = obj->pIndexData->first_affect; paf != NULL; paf = paf->next )
    {
    sprintf( buf, "Affects %s by %d.\n\r",
             affect_loc_name( paf->location ), paf->modifier );
    send_to_char( buf, ch );
    }

  if(obj->pIndexData->obj_prog!=NULL)
    send_to_char( "Object has 'Object program' (TM).\n\r",ch);

  return TRUE;
  }

bool do_castle_rstat( CHAR_DATA *ch, char *argument )
  {
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_INPUT_LENGTH];
  ROOM_INDEX_DATA *location;
  int door;

  one_argument( argument, arg );
  location = ( arg[0] == '\0' ) ? ch->in_room : find_location( ch, arg );
  if ( location == NULL )
    {
    send_to_char( "No such location.\n\r", ch );
    return FALSE;
    }

  if ( location->creator_pvnum!=ch->pcdata->pvnum )
    {
    send_to_char( "You can't stat this room!\n\r", ch );
    return FALSE;
    }

  sprintf( buf, "NAME: '%s'\n\rArea: '%s' level %d.\n\r",
           location->name,
           location->area->name,
           location->area->average_level );
  send_to_char( buf, ch );

  sprintf( buf, "SECTOR: %s.\n\r",
           broken_bits(location->sector_type, "SECT_", TRUE));
  send_to_char( buf, ch );

  sprintf( buf, "room FLAGs: %s.\n\rDESCription:\n\r%s",
           broken_bits(location->room_flags, "CROOM_", FALSE),
           location->description );
  send_to_char( buf, ch );

  if ( location->first_extradesc != NULL )
    {
    EXTRA_DESCR_DATA *ed;

    strcpy( buf, "EXTRA description KEYWORDs: '" );
    for ( ed = location->first_extradesc; ed; ed = ed->next )
      {
      strcat( buf, ed->keyword );
      if ( ed->next != NULL )
        strcat( buf, " " );
      }
    strcat( buf, "'.\n\r");
    send_to_char( buf, ch );
    }

  for ( door = 0; door <= 5; door++ )
    {
    EXIT_DATA *pexit;

    if ( ( pexit = location->exit[door] ) != NULL )
      {
      sprintf( buf, "DOOR: %s.  To: %u.  ",
               broken_bits(door, "DIR_", TRUE),
               pexit->to_room != NULL ? pexit->to_room->vnum : 0);
      send_to_char( buf, ch );
      sprintf( buf, "  KEY: %d.  exit FLAGs: %s.\n\r  KEYWORD: '%s'.  DESCription: %s",
               pexit->key, broken_bits(pexit->exit_info, "CEX_", FALSE),
               pexit->keyword,
               pexit->description[0] != '\0'
                 ? pexit->description : "(none).\n\r" );
      send_to_char( buf, ch );
      }
    }

  return TRUE;
  }

void do_castle( CHAR_DATA *ch, char *argument )
  {
  char arg[MAX_INPUT_LENGTH],buf[81],bigBuf[MAX_STRING_LENGTH],buf2[81];
  CASTLE_DATA *castle;
  int argn,bargain,reconnectEntrance;
  /*ROOM_INDEX_DATA *location;*/

  if ( IS_NPC(ch) )
    return;

  reconnectEntrance=FALSE;

  if(argument[0]=='\0')
    {
    if(ch->pcdata->castle!=NULL)
      {
      castle=ch->pcdata->castle;
      send_to_char("CASTLE: ",ch);
      if(room_index[castle->entrance]==NULL)
        sprintf(bigBuf,"Talk to Order.\n\r");
      else
        sprintf(bigBuf,"Cost so far: %d000\n\r #Rooms: %d #Creatures: %d #Objects: %d\n\rConnect_Room: %s,  Connect_Dir: %s\n\r",
                castle->cost,
                castle->num_rooms, castle->num_mobiles, castle->num_objects,
                (castle->door_room>0)?room_index[castle->door_room]->name:"none",
                (castle->door_room>0)?
                  broken_bits(castle->door_dir,"DIR_",TRUE):"none"
                );
      send_to_char(bigBuf,ch);
      }
    else
      {
      switch(ch->in_room->sector_type)
        {
        case SECT_FIELD:
        case SECT_FOREST:
        case SECT_HILLS:
        case SECT_MOUNTAIN:
	  if ( !IS_SET(ch->in_room->room_flags, ROOM_NO_CASTLE) &&
		!IS_SET(ch->in_room->area->flags, AFLAG_NOCASTLE ) )
            send_to_char("CASTLE: You could start a castle here.\n\r",ch);
	  else
            send_to_char("CASTLE: You can't start a castle here.\n\r",ch);
          break;
        default:
          send_to_char("CASTLE: You can't start a castle here.\n\r",ch);
          break;
        }
      }
    return;
    }

  argument = one_argument( argument, arg );

  /* set up bargain skill */
  bargain=IS_NPC(ch)?100:100-(25*(ch->pcdata->learned[gsn_bargain]))/100;

  castle=ch->pcdata->castle;
  if ( !strcasecmp( arg, "entrance" ) || !strcasecmp( arg, "room" ) )
    {
    EXIT_DATA *pexit,*pexit_rev;
    ROOM_INDEX_DATA *pRoomIndex;
    int vnum,iHash,door,room_cost;

    if(!IS_SET(ch->in_room->room_flags,ROOM_IS_CASTLE))
      {
      switch(ch->in_room->sector_type)
        {
        case SECT_FIELD:
        case SECT_FOREST:
        case SECT_HILLS:
        case SECT_MOUNTAIN:
	if ( IS_SET(ch->in_room->room_flags, ROOM_NO_CASTLE) ||
		IS_SET( ch->in_room->area->flags, AFLAG_NOCASTLE) )
	 {
          send_to_char("You can't build a castle here!\n\r",ch);
          return;
 	 }
          break;
        default:
          send_to_char("You can't build a castle here!\n\r",ch);
          return;
          break;
        }
      }
    else if(castle==NULL)
      {
      send_to_char("You can't build a castle in a castle!\n\r",ch);
      return;
      }
    if(castle!=NULL && ch->in_room->creator_pvnum!=ch->pcdata->pvnum)
      {
      /* OK, check for case of lost entrance, allow them to put one if 
         they aren't currently in someone elses castle */
      if(IS_SET(ch->in_room->room_flags,ROOM_IS_CASTLE))
        {
        send_to_char("You can't put the entrance to your castle in a castle!\n\r",ch);
        return;
        }
      pRoomIndex=room_index[castle->entrance];
      /* make sure their castle->entrance hasn't been screwed up */
      if(pRoomIndex==NULL || ch->pcdata->pvnum!=pRoomIndex->creator_pvnum ||
         !(IS_SET(pRoomIndex->room_flags,ROOM_IS_ENTRANCE)&&
           IS_SET(pRoomIndex->room_flags,ROOM_IS_CASTLE)))
        {/* drat, entrance messed up...fix it */
        for(vnum=20000;vnum<32000;vnum++)
          {
          if((pRoomIndex=room_index[vnum])==NULL)
            continue;
          if(ch->pcdata->pvnum==pRoomIndex->creator_pvnum &&
             IS_SET(pRoomIndex->room_flags,ROOM_IS_ENTRANCE)&&
             IS_SET(pRoomIndex->room_flags,ROOM_IS_CASTLE))
            break;
          }
        if(vnum>=32000||room_index[vnum]==NULL)
          {
          send_to_char("I'm sorry, you don't seem to have a castle, tell the Implementors.\n\r",ch);
          return;
          }
        /* update user's castle structure */
        ch->pcdata->castle->entrance=vnum;

        }
      for ( door = 0; door <= 5; door++ )
        {
        if((pexit=pRoomIndex->exit[door])== NULL)
          continue;
        else
          {
          if(pexit->to_room==NULL || pexit->to_room->vnum==0)
            {
            reconnectEntrance=TRUE;
            argn=rev_dir[door];
            /* connect entrance to this room (code in db.c) */
            if(ch->in_room->exit[argn] != NULL)
              {
              sprintf(buf,"You can't connect your castle here.\n\r  The necessary direction(%s) is blocked.\n\r",dir_name[argn]);
              send_to_char(buf,ch);
              return;
              }
 	    CREATE( pexit_rev, EXIT_DATA, 1);
            top_exit++;
            pexit_rev->description = STRALLOC(pexit->description);
            pexit_rev->keyword = STRALLOC(pexit->keyword);
            pexit_rev->exit_info = pexit->exit_info;
            pexit_rev->pvnum  = pexit->pvnum;
            pexit_rev->key  = pexit->key;
            pexit_rev->vnum  = pRoomIndex->vnum;
            pexit_rev->to_room  = pRoomIndex;
            ch->in_room->exit[argn] = pexit_rev;
            pexit->to_room=ch->in_room;
            castle_needs_saving=TRUE;

            /* show the happenings */
            act("Builders come, work, take a break, and leave.",ch,NULL,NULL,TO_ROOM);
            switch(argn)
              {
              case DIR_UP:
                strcpy(buf2,"above you");
                break;
              case DIR_DOWN:
                strcpy(buf2,"below you");
                break;
              default:
                sprintf(buf2,"to the %s",dir_name[argn]);
                break;
              }
            sprintf(buf,"Builders come and build a room %s!",buf2);
            act(buf, ch, NULL, NULL, TO_CHAR );

            return;
            }
          }
        }
      if(!reconnectEntrance)
        {
        send_to_char("You already have a castle entrance!\n\r",ch);
        return;
        }
      }

    if(!get_bitvector_value(argument,&argn,"DIR_"))
        {
        strcpy(bigBuf,"You must specify a direction for the room!\n\r");
        strcat(bigBuf,"Use: castle room <dir>\n\r");
        strcat(bigBuf,"WHERE: <dir> can be one of:\n\r");
        send_to_char(bigBuf,ch);
        list_bitvectors(ch,"DIR_");
        return;
        }

    if(ch->in_room->exit[argn]!=NULL)
      {
      send_to_char("You cannot add onto this room in that direction!\n\r",ch);
      return;
      }

    /* lets see if you can afford it */
    room_cost=(castle==NULL)?COST_OF_ENTRANCE:COST_OF_ROOM;
    room_cost=(bargain*room_cost)/100*1000;
    if(ch->gold<room_cost)
      {
      sprintf(buf,"It costs $%d to build a room.\n\r",room_cost);
      send_to_char(buf,ch);
      return;
      }
    if(castle!=NULL && castle->num_rooms >= ch->level/4+2)
      {
      send_to_char("You cannot make any more rooms at your level!\n\r",ch);
      return;
      }
    if(castle==NULL)
      {
      CREATE(ch->pcdata->castle, CASTLE_DATA, 1);
      ch->pcdata->castle->entrance=0;
      ch->pcdata->castle->door_room=-1;
      ch->pcdata->castle->door_dir=-1;
      ch->pcdata->castle->has_backdoor=FALSE;
      ch->pcdata->castle->cost=0;
      ch->pcdata->castle->num_rooms=0;
      ch->pcdata->castle->num_mobiles=0;
      ch->pcdata->castle->num_objects=0;
      ch->pcdata->castle->reign_room=0;
      castle=ch->pcdata->castle;
      }
    sprintf(buf,"A contractor comes and takes $%d.\n\r",room_cost);
    send_to_char(buf,ch);
    /* create room */
    sprintf(buf,"The Castle of %s.",ch->name);
    CREATE( pRoomIndex, ROOM_INDEX_DATA, 1);
    pRoomIndex->name        = STRALLOC(buf);
    pRoomIndex->first_person     = NULL;
    pRoomIndex->last_person      = NULL;
    pRoomIndex->first_content    = NULL;
    pRoomIndex->last_content     = NULL;
    pRoomIndex->first_extradesc  = NULL;
    pRoomIndex->last_extradesc   = NULL;
    pRoomIndex->area        = room_index[20000]->area;
    /* find an empty vnum */
    for(vnum=20000;room_index[vnum]!=NULL && vnum<27000;vnum++);
    if(vnum>=27000)
      {
      send_to_char("I'm sorry, you can't create a room, tell the Implementors.\n\r",ch);
      return;
      }

    pRoomIndex->vnum     = vnum;
    pRoomIndex->owned_by    = ch->pcdata->pvnum;
    pRoomIndex->creator_pvnum = ch->pcdata->pvnum;
    pRoomIndex->description = STRALLOC( "  This room is bare of all ornamentation and appears to be relatively new." );
    pRoomIndex->room_flags  =ROOM_IS_CASTLE|ROOM_NO_MOB|ROOM_INDOORS;
    pRoomIndex->sector_type = SECT_INSIDE;
    pRoomIndex->light       = 0;

    for ( door = 0; door <= 5; door++ )
      pRoomIndex->exit[door] = NULL;
    for ( door = 0; door< MAX_LAST_LEFT; door++)
      strcpy( pRoomIndex->last_left[door], "");
    /* new room exit points to old room */
    CREATE(pexit, EXIT_DATA, 1);
    pexit->description      = STRALLOC("");
    pexit->keyword          = STRALLOC("door");
    pexit->exit_info        = 0;
    pexit->pvnum            = -1;
    pexit->key             = -1;
    pexit->vnum             = ch->in_room->vnum;
    pexit->to_room          = ch->in_room;
    pRoomIndex->exit[rev_dir[argn]]= pexit;
    top_exit++;
    /* old rooms exit points to new room */
    CREATE(pexit, EXIT_DATA, 1);
    pexit->description = STRALLOC(buf );
    pexit->keyword        = STRALLOC("door");
    pexit->exit_info = 0;
    pexit->pvnum  = ch->pcdata->pvnum;
    pexit->key  = -1;
    pexit->vnum  = pRoomIndex->vnum;
    pexit->to_room        = pRoomIndex;
    ch->in_room->exit[argn] = pexit;
    top_exit++;
    /* put new room in hash table */
    iHash   = vnum % MAX_KEY_HASH;
    pRoomIndex->next = room_index_hash[iHash];
    room_index_hash[iHash]= pRoomIndex;
    top_room++;
    room_index[vnum]=pRoomIndex;

    if (vnum > pRoomIndex->area->hi_r_vnum)
      pRoomIndex->area->hi_r_vnum = vnum;
    if (vnum < pRoomIndex->area->low_r_vnum)
      pRoomIndex->area->low_r_vnum = vnum;
    /* show the happenings */
    act("Builders come, work, take a break, and leave.",ch,NULL,NULL,TO_ROOM);
    switch(argn)
      {
      case DIR_UP:
        strcpy(buf2,"above you");
        break;
      case DIR_DOWN:
        strcpy(buf2,"below you");
        break;
      default:
        sprintf(buf2,"to the %s",dir_name[argn]);
        break;
      }
    sprintf(buf,"Builders come and build a room %s!",buf2);
    act(buf, ch, NULL, NULL, TO_CHAR );

    /* modify the appropriate character and castle data */
    ch->gold-=room_cost;
    castle->cost+=room_cost/1000;
    castle_needs_saving=TRUE;
    if(castle->entrance==0)
      {
      SET_BIT(pRoomIndex->room_flags,ROOM_SAFE); /* entrance is safe */
      SET_BIT(pRoomIndex->room_flags,ROOM_IS_ENTRANCE);
      castle->entrance=vnum;
      }
    castle->num_rooms+=1;
       
    return;
    }

  if (castle==NULL)
    {
    send_to_char("You have no castle established yet.\n\r",ch);
    return;
    }

  if ( !strcasecmp( arg, "door" ) )
    {
    send_to_char("The 'castle door...' command has changed to 'castle connect...'\n\r",ch);
    return;
    }
  if ( !strcasecmp( arg, "connect" ) )
    {
    EXIT_DATA *pexit,*castleexit;
    int door_cost;
    bool clanfounder=FALSE;

    if(!strcasecmp(argument,"clear"))
      {
      castle->door_room=-1;
      castle->door_dir=-1;
      return;
      }
    if (ch->pcdata->clan !=NULL && ch->pcdata->clan &&
	 !strcasecmp( ch->name, ch->pcdata->clan->leader  ) )
	clanfounder=TRUE;

    if (ch->in_room->creator_pvnum!=ch->pcdata->pvnum &&
        castle->has_backdoor && !clanfounder)
      {
      send_to_char("You can only have ONE back door!\n\r",ch);
      return;
      }

    /* lets see if you can afford it */
    if(ch->in_room->creator_pvnum!=ch->pcdata->pvnum)
      door_cost=UMAX(COST_OF_BACKDOOR,ch->level*900);
    else
      door_cost=COST_OF_DOOR;
    door_cost=(bargain*door_cost)/100*1000;
    if(ch->gold<door_cost)
      {
      if(ch->in_room->creator_pvnum!=ch->pcdata->pvnum)
        {
        sprintf(buf,"It costs $%d to build a BACK door.\n\r",door_cost);
        send_to_char(buf,ch);
        return;
        }
      sprintf(buf,"It costs $%d to build a connection.\n\r",door_cost);
      send_to_char(buf,ch);
      return;
      }
    if(!get_bitvector_value(argument,&argn,"DIR_")&&(castle->door_room==-1))
      {
      strcpy(bigBuf,"You must specify a direction for the first side of a connection!\n\r");
      strcat(bigBuf,"Use: castle connect <dir>\n\r");
      strcat(bigBuf,"WHERE: <dir> can be one of:\n\r");
      send_to_char(bigBuf,ch);
      list_bitvectors(ch,"DIR_");
      return;
      }
    /* default direction is opposite of first one */
    if(castle->door_room!=-1 && argn==-1)
      argn=rev_dir[castle->door_dir];
    if(ch->in_room->exit[argn]!=NULL)
      {
      send_to_char("You cannot put a connection in that direction!\n\r",ch);
      return;
      }
    if(!IS_SET(ch->in_room->room_flags,ROOM_IS_CASTLE))
      {
      switch(ch->in_room->sector_type)
        {
        case SECT_FIELD:
        case SECT_FOREST:
        case SECT_HILLS:
        case SECT_MOUNTAIN:
	if ( IS_SET(ch->in_room->room_flags, ROOM_NO_CASTLE) ||
		IS_SET( ch->in_room->area->flags, AFLAG_NOCASTLE) )
	 {
          send_to_char("You cannot put a connection in this room!\n\r",ch);
          return;
 	 }
          break;
        default:
          send_to_char("You cannot put a connection in this room!\n\r",ch);
          return;
          break;
        }
      }
/*
    if(IS_SET(ch->in_room->room_flags,ROOM_NO_RECALL) ||
        IS_SET( ch->in_room->area->flags, AFLAG_NOTELEPORT ) || 
	IS_SET( ch->in_room->area->flags, AFLAG_NORECALL ) || 
	IS_SET( ch->in_room->area->flags, AFLAG_NOCASTLE ) )
      {
      send_to_char("You cannot put a connection in this room!\n\r",ch);
      return;
      }
*/
    if(castle->door_room==-1)
      {
      castle->door_room=ch->in_room->vnum;
      castle->door_dir=argn;
      send_to_char("Now you have to go define the other side of the connection.\n\r",ch);
      return;
      }
    if(room_index[castle->door_room]->exit[castle->door_dir]!=NULL)
      {
      send_to_char("Your first connection is in an invalid direction!  Clearing first connection.\n\r",ch);
      castle->door_room=-1;
      castle->door_dir=-1;
      return;
      }
    if(((ch->in_room->creator_pvnum!=ch->pcdata->pvnum)||
        (room_index[castle->door_room]->creator_pvnum!=ch->pcdata->pvnum)) &&
       (IS_SET(ch->in_room->room_flags,ROOM_IS_ENTRANCE) ||
        IS_SET(room_index[castle->door_room]->room_flags,ROOM_IS_ENTRANCE)))
      {
      send_to_char("You can't have a backdoor from your entrance!\n\r",ch);
      return;
      }
    /* make sure they aren't creating links from outside to outside */
    if((ch->in_room->creator_pvnum!=ch->pcdata->pvnum)&&
       (room_index[castle->door_room]->creator_pvnum!=ch->pcdata->pvnum))
      {
      send_to_char("You can't make a connection between two outside areas.\n\r",ch);
      return;
      }
    /* check for back door creation in reverse */
    if(room_index[castle->door_room]->creator_pvnum!=ch->pcdata->pvnum)
      {
      door_cost=UMAX(COST_OF_BACKDOOR,ch->level*900);
      door_cost=(bargain*door_cost)/100*1000;
      /* darn, changed cost so check funds again */
      if(ch->gold<door_cost)
        {
        sprintf(buf,"It costs $%d to build a BACK door.\n\r",door_cost);
        send_to_char(buf,ch);
        }
      }
    /* other rooms exit points to room */
    castleexit=NULL;
    if(room_index[castle->door_room]->creator_pvnum==ch->pcdata->pvnum)
      {
      CREATE(pexit, EXIT_DATA, 1);
      pexit->description      = STRALLOC("");
      pexit->keyword          = STRALLOC("door");
      pexit->exit_info        = 0;
      pexit->pvnum            = ch->pcdata->pvnum;
      pexit->key             = -1;
      pexit->vnum             = ch->in_room->vnum;
      pexit->to_room          = ch->in_room;
      room_index[castle->door_room]->exit[castle->door_dir]= pexit;
      top_exit++;
      castleexit=pexit;
      }
    /* room exit points to other room */
    if(room_index[ch->in_room->vnum]->creator_pvnum==ch->pcdata->pvnum)
      {
      CREATE(pexit, EXIT_DATA, 1);
      pexit->description      = STRALLOC("");
      pexit->keyword        = STRALLOC("door");
      pexit->exit_info = 0;
      pexit->pvnum  = ch->pcdata->pvnum;
      pexit->key  = -1;
      pexit->vnum  = castle->door_room;
      pexit->to_room        = room_index[castle->door_room];
      ch->in_room->exit[argn] = pexit;
      top_exit++;
      castleexit=pexit;
      }

    act("Builders come, take a break, and leave.",ch,NULL,NULL,TO_ROOM);
    send_to_char("The door has been made.\n\r",ch);

    /* modify the appropriate character and castle data */
    ch->gold-=door_cost;
    castle->cost+=door_cost/1000;
    castle_needs_saving=TRUE;
    castle->door_room=-1;
    castle->door_dir=-1;
    if((ch->in_room->creator_pvnum!=ch->pcdata->pvnum &&
        !IS_SET(ch->in_room->room_flags,ROOM_RIP))||
       (castleexit->to_room->creator_pvnum!=ch->pcdata->pvnum &&
        !IS_SET(castleexit->to_room->room_flags,ROOM_RIP)))
      {
      castle->has_backdoor=TRUE;
      if (!clanfounder)
        SET_BIT(castleexit->exit_info,EX_BACKDOOR);
      else
	{
         SET_BIT(castleexit->exit_info,EX_CLAN_BACKDOOR);
   	 ch->pcdata->clan->num_backdoors++;
	 ch_printf(ch, "You just made a clan-wide backdoor for %s.\n\r",
	           ch->pcdata->clan->name);
	}
      }

    return;
    }

  if (ch->in_room->creator_pvnum!=ch->pcdata->pvnum)
    {
    send_to_char("You are NOT in your castle!\n\r",ch);
    return;
    }

  if ( !strcasecmp( arg, "rstat" ) )
    {
    int stat_cost;
    /* make sure they can afford it */

    stat_cost=(bargain*COST_OF_STAT)/100*1000;
    if(ch->gold<stat_cost)
      {
      sprintf(buf,"It will cost you $%d to do an rstat.\n\r",stat_cost);
      send_to_char(buf,ch);
      return;
      }
    if(do_castle_rstat(ch,argument))
      {
      /* adjust cash situation */
      ch->gold-=stat_cost;
      castle->cost+=stat_cost/1000;
      }
    return;
    }
  else if ( !strcasecmp( arg, "mstat" ) )
    {
    int stat_cost;
    /* make sure they can afford it */

    stat_cost=(bargain*COST_OF_STAT)/100*1000;
    if(ch->gold<stat_cost)
      {
      sprintf(buf,"It will cost you $%d to do an mstat.\n\r",stat_cost);
      send_to_char(buf,ch);
      return;
      }
    if(do_castle_mstat(ch,argument))
      {
      /* adjust cash situation */
      ch->gold-=stat_cost;
      castle->cost+=stat_cost/1000;
      }
    return;
    }
  else if ( !strcasecmp( arg, "ostat" ) )
    {
    int stat_cost;
    /* make sure they can afford it */

    stat_cost=(bargain*COST_OF_STAT)/100*1000;
    if(ch->gold<stat_cost)
      {
      sprintf(buf,"It will cost you $%d to do an ostat.\n\r",stat_cost);
      send_to_char(buf,ch);
      return;
      }
    if(do_castle_ostat(ch,argument))
      {
      /* adjust cash situation */
      ch->gold-=stat_cost;
      castle->cost+=stat_cost/1000;
      }
    return;
    }

  else if ( !strcasecmp( arg, "ocreate" ) )
    {
    }
  else if ( !strcasecmp( arg, "oset" ) )
    {
    }
  else
    {
    send_to_char("What Castle command were you wanting to do? (see: HELP CASTLE)\n\r",ch);
    return;
    }
  return;
  }

void del_castle( CHAR_DATA *victim)
{
  int vnum;
  ROOM_INDEX_DATA *pRoomIndex;
  MOB_INDEX_DATA *pMobIndex; 

  if(victim->pcdata->castle==NULL)
    return;

  for(vnum=20000;vnum<32000;vnum++)
    {
   if( ( (pRoomIndex=room_index[vnum]) !=NULL) 
       && victim->pcdata->pvnum==pRoomIndex->creator_pvnum 
       && IS_SET(pRoomIndex->room_flags,ROOM_IS_CASTLE))
      {
       delete_room(pRoomIndex);
      }
    if( ( (pMobIndex=mob_index[vnum]) !=NULL) 
       && victim->pcdata->pvnum==pMobIndex->creator_pvnum )
      {
       delete_mob(pMobIndex);
      }

    }
  /* update players castle structure */
  victim->pcdata->castle->entrance=0;
  victim->pcdata->castle->door_room=-1;
  victim->pcdata->castle->door_dir=-1;
  castle_needs_saving=TRUE;
  victim->pcdata->castle->has_backdoor=FALSE;
  victim->pcdata->castle->cost=0;
  victim->pcdata->castle->num_rooms=0;
  victim->pcdata->castle->num_mobiles=0;
  victim->pcdata->castle->num_objects=0;
  victim->pcdata->castle->reign_room=0;
  victim->pcdata->castle=NULL;
}

void clear_castles(void)
{
 return;
}