FlCodebase3.1/
FlCodebase3.1/bounty/
FlCodebase3.1/challenge/
FlCodebase3.1/clans/
FlCodebase3.1/gods/
FlCodebase3.1/mobprogs/
FlCodebase3.1/player/
FlCodebase3.1/savemud/
/***************************************************************************
 *  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 Envy Diku Mud, you must comply with   *
 *  the original Diku license in 'license.doc', the Merc license in        *
 *  'license.txt', as well as the Envy license in 'license.nvy'.           *
 *  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.                                                  * 
 *                                                                         *
 *      ROM 2.4 is copyright 1993-1998 Russ Taylor                         *
 *      ROM has been brought to you by the ROM consortium                  *
 *          Russ Taylor (rtaylor@hypercube.org)                            *
 *          Gabrielle Taylor (gtaylor@hypercube.org)                       *
 *          Brian Moore (zump@rom.org)                                     *
 *      By using this code, you have agreed to follow the terms of the     *
 *      ROM license, in the file Rom24/doc/rom.license                     *
 *                                                                         *
 * Code Adapted and Improved by Abandoned Realms Mud                       *
 * and Aabahran: The Forsaken Lands Mud by Virigoth                        *
 *                                                                         *
 * Continued Production of this code is available at www.flcodebase.com    *
 ***************************************************************************/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "jail.h"
#include "bounty.h"
#include "interp.h"
#include "recycle.h"
#include "cabal.h"
#include "olc.h"




/* Written by: Virigoth
 *  returns: number of rares transfered
 *  comments: takes a sorted group (highest to lowest level) of rares and			*
 *  transfers them to ch.  Number of rare items taken is "number", ignores owner only items	*
 * if fRandom then level is ignored and random rares are transfered				*/
int get_random_rares( CHAR_DATA* ch, CHAR_DATA* victim, int number, bool fRandom){
  const int MAX_OBJ = 32;
  OBJ_DATA* bag;
  OBJ_DATA* rares[MAX_OBJ];
  int max_rares = 0;
  int trans = 0;

  OBJ_DATA* obj, *obj_next;
  int i = 0;

/* first cycle through the victim's items, and put limited pointers into "rares" */
  for ( obj = victim->carrying; obj != NULL; obj = obj_next ){
    obj_next = obj->next_content;
      
    if (obj->wear_loc == WEAR_TATTOO
	|| !IS_LIMITED(obj) 
	|| IS_SET(obj->wear_flags, ITEM_HAS_OWNER)
	|| is_affected_obj(obj, gen_malform)
	|| is_affected_obj(obj, gen_hwep)
	|| !can_take( ch, obj ) )
      continue;

    rares[max_rares++] = obj;
  }

  if (max_rares < 1)
    return trans;

/* sort the rares from highest level to lowest */
  for (i = 1; i < max_rares; i++){
    int j = 0;
    for (j = 0; j  < max_rares - i; j ++ ){
      obj = rares[j];
      obj_next = rares[j + 1];

      if (obj_next->level > obj->level){
	rares[j + 1] = obj;
	rares[j] = obj_next;
      }
    }
  }
  /* create a bag */
  if ( (bag = create_object(get_obj_index(OBJ_VNUM_JAILBAG), 0)) == NULL){
    bug("get_random_rares: Could not create a jailbag", 0);
    return 0;
  }
  else{
    char buf[MIL];
    /* set the desc. and details */
    sprintf( buf, bag->name, victim->name );
    free_string( bag->name );
    bag->name = str_dup( buf );
    sprintf( buf, bag->short_descr, victim->name );
    free_string( bag->short_descr );
    bag->short_descr = str_dup( buf );
    sprintf( buf, bag->description, victim->name );
    free_string( bag->description );
    bag->description = str_dup( buf );
  }

/* run through number of rares and either pull from top or select randomly */
  if (fRandom){
    for (i =0; i < number; i++){
      int index = number_range(0, max_rares - 1);
      obj = rares[index];

      REMOVE_BIT(obj->extra_flags,ITEM_INVENTORY);
      obj_from_char( obj );
      if (ch == victim)
	extract_obj( obj );
      else
	obj_to_obj( obj, bag );
      trans ++;
      rares[index] = rares[max_rares--];
      if (max_rares < 1)
	return trans;
    }
  }
  else{
    for (i =0; i < number && i < max_rares; i++){
      obj = rares[i];

      REMOVE_BIT(obj->extra_flags,ITEM_INVENTORY);
      obj_from_char( obj );
      if (ch == victim)
	extract_obj( obj );
      else
	obj_to_obj( obj, bag );
      trans++;
    }
  }
  if (trans > 0)
    obj_to_char( bag, ch );
  else
    extract_obj( bag );
  return trans;
}
  

/* Written by: Virigoth
 *   returns: pointer to the bag
 *   comments: Strips victim of all objects and deposits into OBJ_VNUM_JAILBAG
 *   which is placed on ch. (fLimOnly = TRUE causes only limited items to be bagged) *
 *  fAll causes all items on character to be put in the bag (minus tattoo) */
OBJ_DATA* create_jailbag(CHAR_DATA* ch, CHAR_DATA* victim, bool fLimOnly, bool fAll){
  OBJ_DATA* bag = NULL;
  OBJ_DATA* obj, *obj_next;
  char buf[MIL];
  
  int dur = 60;

  /* we run through all belongings and move to the bag.  The bag should be made in OLC
     in such way as to prevent any other object frombeing put in there. */
  
  if (ch->in_room == NULL)
    return NULL;
  /* PC only */
  if (IS_NPC(victim))
    return NULL;
  if (IS_IMMORTAL(victim))
    return NULL;
  /* hard core cirminals get everything stripped */
  if (victim->pcdata->flagged >= 5)
    fLimOnly = FALSE;

  /*Viri:  new jail bag each death, was causing too much headache with incorrectly linked objects
    for ( obj = victim->carrying; obj != NULL; obj = obj_next ){
    obj_next = obj->next_content;
    if (obj->pIndexData->vnum == OBJ_VNUM_JAILBAG
    && is_name(victim->name, obj->name))
    bag = obj;
    }
	    
    if (!bag){
      for ( obj = ch->carrying; obj != NULL; obj = obj_next )
	{
	obj_next = obj->next_content;
	  if (obj->pIndexData->vnum == OBJ_VNUM_JAILBAG
	      && is_name(victim->name, obj->name))
	    bag = obj;
	}
    }
    */

  if (!bag) {
    /* if no existin bag with victims name on victim or ch we make new one */
    if ( (bag = create_object(get_obj_index(OBJ_VNUM_JAILBAG), 0)) == NULL){
      bug("create_jailbag: Could not create a jailbag", 0);
      return NULL;
    }
  }
  
  /* set the desc. and details */
  sprintf( buf, bag->name, victim->name );
  free_string( bag->name );
  bag->name = str_dup( buf );
  sprintf( buf, bag->short_descr, victim->name );
  free_string( bag->short_descr );
  bag->short_descr = str_dup( buf );
  sprintf( buf, bag->description, victim->name );
  free_string( bag->description );
  bag->description = str_dup( buf );
  
  
  /* start transfer */
  if (!fLimOnly && victim->gold > 0 ){
    obj_to_obj(create_money(victim->gold), bag);
    victim->gold = 0;
  }
  
  if (!IS_IMMORTAL(victim)){
    for ( obj = victim->carrying; obj != NULL; obj = obj_next ){
      obj_next = obj->next_content;
      
      if (obj->wear_loc == WEAR_TATTOO)
	continue;
      
      if (!fAll){
	if (fLimOnly && !IS_LIMITED(obj)) 
	  continue;
	
	if (IS_SET(obj->wear_flags, ITEM_HAS_OWNER))
	  continue;
	if( is_affected_obj(obj, gen_malform)
	    || is_affected_obj(obj, gen_hwep))
	  continue;
      }
      REMOVE_BIT(obj->extra_flags,ITEM_INVENTORY);
      obj_from_char( obj );
      obj_to_obj( obj, bag );
    }
  }
 /* dont create a bag if empty or ch == victim */
  if (!bag->contains || ch == victim){
    extract_obj(bag);
    return NULL;
  }
  
    /* move the bag to ch automaticly */
    obj_to_char(bag, ch);

    /* set the timer to prevent abuse */
    bag->timer = dur;
    return bag;
}

/* finds a random justice and and jails the victim using that justice */
CHAR_DATA* surrender( CHAR_DATA* victim ){
  const int  max_justice = 16;
  CHAR_DATA* justice[max_justice];
  int last_justice = 0;
  
  CHAR_DATA* vch;
  
  for (vch = player_list; vch; vch = vch->next_player ){
    if (!IS_IMMORTAL(vch) && vch->pCabal && IS_CABAL(vch->pCabal, CABAL_JUSTICE))
      justice[last_justice++] = vch;
  }

  if (last_justice < 1)
    return victim;
  else
    vch = justice[number_range(0, last_justice - 1)];

  act("A guard drags $N towards you handing $M to you.", vch, NULL, victim, TO_CHAR );
  act("A guard drags you towards $n handing you to $m.", vch, NULL, victim, TO_VICT );

  return vch;
}

/* returns position in jail_table, based on current room vnum  */
int jail_cell_lookup(int vnum){
  int jail = 0;

  for (jail = 0; jail < MAX_HOMETOWN; jail ++){
    int cell = 0;
    /* search through each hometown for matching vnum of room */
    if (!jail_table[jail].name)
      break;
    /* check each cell */
    for (cell = 0; cell < MAX_CELL; cell++){
      if (!jail_table[jail].cell[cell])
	continue;
      if (jail_table[jail].cell[cell] == vnum){
	return jail;
      }
    }//END cell match
  }//END jail search
  return 0;
}

/* returns spot in execution_Table */
int jexecution_lookup(const char *name)
{
   int e;
   for ( e = 0; execution_table[e].name != NULL; e++){
     if (!execution_table[e].name[0])
       continue;
     if (LOWER(name[0]) == LOWER(execution_table[e].name[0]) 
	 && !str_prefix( name, execution_table[e].name))
       return e;
   }
   return 0;
}
/* Written by: Virigoth							*
 * Returns: pointer to paf with gen_jail so name of justice can be set.	*
 * Used: jail.c, effect.c						*
 * Comment: Sets a current sentance based on "type" and "level".  Type  *
 * is JAIL_XXX from jail.h, level is severity which affects things based*
 * on type. Ch is the person to have gen_jail set/changed		*/

AFFECT_DATA* set_sentence(CHAR_DATA* ch, int type, int level){
  AFFECT_DATA* paf, af;
  CHAR_DATA* wch;

  char buf[MIL];
  char buf2[MIL];
  int cur_dur = 0;

  /* poor man flag for change */
  buf[0] = '\0';

  /* set common things */
  af.type = gen_jail;
  af.where = TO_AFFECTS;
  af.bitvector  = 0;
  af.location = APPLY_NONE;

  /* check if there is existing duration/type */
  if ( (paf = affect_find(ch->affected, gen_jail)) != NULL)
    cur_dur = paf->duration;


  switch(type){
  default:
    bug("set_sentence: Unkown type.", 0);
    return NULL;
    /* NORMAL */
  case JAIL_NORMAL:
    af.modifier = JAIL_NORMAL;
    af.duration = DUR_NORMAL;
    af.level = 0;
    sprintf(buf, "Normal for %d hours", af.duration);
    break;
    /* BAIL */
  case JAIL_BAIL:
    af.modifier = JAIL_BAIL;
    af.duration = UMAX(DUR_BAIL, cur_dur);
    af.level = level;
    sprintf(buf, "Bail of %d gold for %d hours (Use \"bail\" to pay)",
	    SEV_BAIL * level, af.duration);
    break;
    /* EXTENDED */
  case JAIL_EXTENDED:
    af.modifier = JAIL_EXTENDED;
    af.duration = UMAX(5, DUR_EXTENDED + (SEV_EXTENDED * level) - (DUR_NORMAL - cur_dur));
    af.level = level;
    sprintf(buf, "Extended for %d hours.", af.duration);
    break;
    /* EXECUTION */
  case JAIL_EXECUTE:
    af.modifier = JAIL_EXECUTE;
    af.duration = DUR_EXECUTE;
    af.level = level;
    sprintf(buf, "Execution in %d hours.", af.duration);
    break;
  case JAIL_RELEASE:
    af.modifier = JAIL_RELEASE;
    af.duration = DUR_RELEASE;
    af.level = level;
    sprintf(buf, "Release in %d hours.", af.duration);
    break;
  }
  act_new("Your sentence has been set to $t.", ch, buf, NULL, TO_CHAR, POS_DEAD);
  sprintf(buf2, "%s's sentence has been set to %s.", PERS2(ch), buf);

  /* broadcast on justice channel */
  for ( wch = char_list; wch != NULL; wch = wch->next ){
    if ( IS_NPC(wch) && IS_SET(wch->off_flags,CABAL_GUARD)
	 && wch->pIndexData->group == VNUM_JUSTICE ){
      REMOVE_BIT(wch->comm,COMM_NOCHANNELS);
      REMOVE_BIT(wch->comm,COMM_NOCABAL);
      do_jcabaltalk(wch, buf2);
      SET_BIT(wch->comm,COMM_NOCABAL);
      SET_BIT(wch->comm,COMM_NOCHANNELS);
      break;
    }
  }//END CABAL CHANNEL TALK

    /* conclave gets reported when someone gets thrown injail */
  if (type == JAIL_NORMAL){
    sprintf(buf2, "Contacts report of %s's arrival in %s.", PERS2(ch), ch->in_room->area->name);
    for ( wch = char_list; wch != NULL; wch = wch->next ){
      if ( IS_NPC(wch) && IS_SET(wch->off_flags,CABAL_GUARD)
	   && wch->pIndexData->group == VNUM_LEGION ){
	REMOVE_BIT(wch->comm,COMM_NOCHANNELS);
	REMOVE_BIT(wch->comm,COMM_NOCABAL);
	do_cabaltalk(wch, buf2);
	SET_BIT(wch->comm,COMM_NOCABAL);
	SET_BIT(wch->comm,COMM_NOCHANNELS);
	break;
      }
    }
  }
  /* decide between new paf, or current */
  if (paf){
    paf->modifier = af.modifier;
    paf->duration = af.duration;
    paf->level = level;
    return paf;
  }
  return affect_to_char(ch, &af);
}

/* Written by: Virigoth							*
 * Returns: pointer of cell to put char. in, requires first cell in 	*
 * jail_table to contain cells and data to be used in case of no match  *
 * found								*
 * Used: jail.c,							*
 * Comment: Jailcells stored in jail_table, cell is based on justice    *
 * hometown, if no jail cells found there, it will search for first jail*
 * possible								*/

ROOM_INDEX_DATA* get_jailcell(int hometown){
  int jail = jail_lookup(hometown_table[hometown].name);
  int small = 9999;
  int cell = 0;
  ROOM_INDEX_DATA* ret_cell = NULL;
  AREA_DATA* pArea;

  // first check if the hometown is lawful
  if ( (pArea = get_area_data_str(jail_table[jail].name)) != NULL
       && !IS_AREA(pArea, AREA_LAWFUL)){
    /* check all jails pick first lawful city with jail */
    int jaill;
    for ( jaill = 0; jail_table[jaill].name != NULL && jaill < MAX_HOMETOWN; jaill++){
      if ( (pArea = get_area_data_str(jail_table[jaill].name)) != NULL
	   && IS_AREA(pArea, AREA_LAWFUL))
	jail = jaill;
    }
  }
  /* we need to traverse through the cells in the given city
     and select the one with lowest amount of characters */
  for (cell = 0; cell < MAX_CELL; cell++){
    ROOM_INDEX_DATA* room;
    CHAR_DATA* vch;
    int count = 0;

    /* skip 0 cells */
    if (!jail_table[jail].cell[cell])
      continue;
    /* get the room, check if exists */
    if ( (room = get_room_index(jail_table[jail].cell[cell])) == NULL){
      char buf[MIL];
      sprintf(buf, "get_jailcell: cell %d does not exist.", 
	      jail_table[jail].cell[cell]);
      bug(buf, 0);
      return NULL;
    }

    /* count PC's in the room */
    for (vch = room->people; vch; vch = vch->next_in_room){
      if (!IS_NPC(vch) && (vch->pCabal == NULL || !IS_CABAL(vch->pCabal, CABAL_JUSTICE)))
	count++;
    }

    /* decide if this room is the one with least people */
    if (count < small){
      small = count;
      ret_cell = room;
    }
    /* continue the search */
  }
  /* search over, make sure there is a room at all */
  if (!ret_cell){
    char buf[MIL];
    sprintf(buf, "get_jailcell: No valid cell found for hometown %d.", 
	    hometown);
    bug(buf, 0);
  }
  return ret_cell;

}

/* Written by: Virigoth							*
 * Returns: Void							*
 * Used: jail.c,							*
 * Comment: Causes the exe_mob as per jail_table to yell the string	*
 * the mob is created at the "guardhouse" room, then destroyed		*/
void jail_announce(int jail, char* string){
  CHAR_DATA* mob;
  ROOM_INDEX_DATA* room;

  /* safety */
  if (!string)
    return;
  if (jail > MAX_HOMETOWN){
    bug("jail_announce: jail was greater then MAX_HOMETOWN.", 0);
    return;
  }
  /* Grab the room to be yelled in*/
  if ( (room = get_room_index(jail_table[jail].exe_room))  == NULL){
    char buf[MIL];
    sprintf(buf, "jail_announce: room %d does not exist.", 
	    jail_table[jail].exe_room);
    bug(buf, 0);
    return;
  }
  /* grab the mob to do the yelling */
  if ( (mob = create_mobile( get_mob_index(jail_table[jail].exe_mob)))  == NULL){
    char buf[MIL];
    sprintf(buf, "jail_announce: mob %d does not exist.", 
	    jail_table[jail].exe_mob);
    bug(buf, 0);
    return;
  }

    /* move mob to the right room, yell, and cleanup */
    char_to_room(mob, room);
    REMOVE_BIT(mob->comm,COMM_NOYELL);
    REMOVE_BIT(mob->comm,COMM_NOCHANNELS);
    do_yell(mob, string);
    SET_BIT(mob->comm,COMM_NOYELL);
    SET_BIT(mob->comm,COMM_NOCHANNELS);
    /* just in case something did hit him */
    stop_fighting(mob, FALSE);
    char_from_room(mob);
    extract_char(mob, TRUE);
}

/* Allows a criminal to surrender */
void do_surrender( CHAR_DATA* ch, char* argument ){
  
  if (IS_OUTLAW( ch )){
    send_to_char("Go fall on a sword instead.\n\r", ch);
    return;
  }
  else if (!IS_WANTED( ch )){
    send_to_char("You have not been marked a criminal.\n\r", ch);
    return;
  }
  else if (is_affected(ch, gen_jail) || IS_SET(ch->in_room->room_flags2, ROOM_JAILCELL)){
    send_to_char("You're already in jail.\n\r", ch);
    return;
  }
  else if (is_fight_delay( ch, 180 )){
    send_to_char("You cannot surrender after recent combat.\n\r", ch);
    return;
  }
  else if (IS_NULLSTR(argument)){
    send_to_char("Are you sure you wish to surrender to forces of Law?\n\rUse \"surrender confirm\" to confirm.\n\r", ch );
    return;
  }
  else{
    char buf[MIL];
    sprintf( buf, "%s has chosen to surrender to our judgement.", PERS2( ch ));
    cabal_echo_flag( CABAL_JUSTICE, buf );
    jail_char( ch, ch );
  }
}

/* Written by: Virigoth							*
 * Returns: Void							*
 * Used: fight.c,							*
 * Comment: Checkes for wanted status, and transports victim to correct jail*
 * if needed. Sets gen_jail if needed.	jail selected based on ch home  */

void jail_char(CHAR_DATA* cha, CHAR_DATA* victim){
  CHAR_DATA* ch  = cha;
  ROOM_INDEX_DATA* cell;
  AFFECT_DATA* paf;
  AREA_DATA* pArea;
  char buf[MIL];
  int max_pen = 0, crime = 0;

  /* check for problems */
  if (!ch || !victim){
    bug("jail_char: NULL ch or victim passed.", 0);
    return;
  }

  if (IS_NPC(victim)){
    bug("jail_char: victim NPC passed.", 0);
    return;
  }
  /* check for wanted status */
  if (!IS_SET(victim->act,PLR_WANTED))
    return;
  /* check for charmies */
  if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM)){
    if (ch->leader)
      ch = ch->leader;
    else if (ch->master)
      ch = ch->master;
    else{
      bug("jail_char: NPC without master passed.", 0);
      return;
    }
  }
  /* check for mob apprehension */
  else if (IS_NPC(ch) || ch == victim)
    ch = surrender( victim );
  
  /* grab the jail cell to transport too */
  if ( (cell = get_jailcell(ch->hometown)) == NULL){
    char buf[MIL];
    sprintf(buf, "jail_char: get_jailcell returned NULL for town of %s.", 
	    hometown_table[ch->hometown].name);
    bug(buf, 0);
    return;
  }

  /* stop the fight, make things all safe so victim doesnt die in cell */
  stop_fighting( victim, TRUE );
  if (IS_AFFECTED2(victim,AFF_RAGE))
    {
      REMOVE_BIT(victim->affected2_by,AFF_RAGE);
      affect_strip(victim,gsn_rage);
    }
  affect_strip(victim,gsn_poison);
  affect_strip(victim,gsn_plague);
  affect_strip(victim,gen_bleed);
  affect_strip(victim,gsn_insect_swarm);
  affect_strip(victim, skill_lookup("visitation"));
  affect_strip(victim,skill_lookup("dysentery"));

  victim->pcdata->condition[COND_HUNGER]=45;
  victim->pcdata->condition[COND_THIRST]=45;    
  victim->hit = UMAX(1, 25 * victim->max_hit / 100);
  victim->move = 25 * victim->max_move / 100;
  victim->mana = 0 * victim->max_mana / 100;
  victim->position = POS_RESTING;
  die_follower(victim, FALSE);

  /* get the belongings for die hard criminals, if ch and victim are same (surrender) items are poofed */
  if (victim->pcdata->flagged > 11 ){		/* 10+ */
    create_jailbag(ch, victim, TRUE, FALSE);
  }
  else if (victim->pcdata->flagged > 6 ){		/* 6 - 10 */
    int num = get_random_rares( ch, victim, 6, FALSE );
    sendf( ch, "You recive %d item%s from %s.\n\r", num, num == 1 ? "" : "s", PERS2( victim ));
    sendf( victim, "You lost %d item%s.\n\r", num, num == 1 ? "" : "s");
  }
  else if (victim->pcdata->flagged > 3 ){		/* 3 - 5 */
    int num = get_random_rares( ch, victim, 3, FALSE );
    sendf( ch, "You recive %d item%s from %s.\n\r", num, num == 1 ? "" : "s", PERS2( victim ));
    sendf( victim, "You lost %d item%s.\n\r", num, num == 1 ? "" : "s");
  }
  else if (victim->pcdata->flagged > 1 ){		/* 1 - 2 */
    int num = get_random_rares( ch, victim, 1, TRUE );
    sendf( ch, "You recive %d item%s from %s.\n\r", num, num == 1 ? "" : "s", PERS2( victim ));
    sendf( victim, "You lost %d item%s.\n\r", num, num == 1 ? "" : "s");
  }
  

  /* Print some text and move the victim */
  if (ch != victim ){
    act("As you lose your consciousness you see a swarm of guards surround you quickly.", ch, NULL, victim, TO_VICT);
    act("As $N loses $S consciousness you call onto guards to capture $M.", ch, NULL, victim, TO_CHAR);
    act("As $N loses $S consciousness $n calls onto guards to capture $M.", ch, NULL, victim, TO_NOTVICT);
  }
  else{
    act("The guards lead you away.\n\r", ch, NULL, victim, TO_CHAR );
  }

  /* give credit */
  if (ch != victim
      && IS_CABAL(ch->pCabal, CABAL_JUSTICE)
      && IS_SET(victim->act,PLR_WANTED)
      && !IS_SET(ch->in_room->room_flags2, ROOM_JAILCELL)
      && !is_affected(ch, gen_jail)){
    cp_event(ch, victim, NULL, CP_EVENT_CAPTURE);
  }

  /* boost the relations between the justice and royals of areas that this person commited crimes in */
  for (paf = victim->affected; paf; paf = paf->next ){
    if (paf->type == gsn_wanted && paf->bitvector){
      /* crime found/wanted we increase the relations but need area first */ 
      if ( (pArea = get_area_data( paf->location )) == NULL){
	bug("jail_char: could not get area for vnum %d.", paf->location);
	continue;
      }
      else if (pArea->pCabal)
	affect_justice_relations(pArea->pCabal, 50);
    }
  }
  /* move the victim */
  act("The guards quickly carry $N off to $S jailcell.", ch, NULL, victim, TO_NOTVICT);
  char_from_room(victim);
  char_to_room(victim, cell);
  act("A small squad of justice guards throws $n into the cell.", victim, NULL, NULL, TO_ROOM);
  do_look(victim, "auto");


  /* get the maximum penalty based on "wanted" effect */
  crime = show_crimes( victim, victim, TRUE, TRUE );
  switch ( crime ){
  case CRIME_LIGHT:
    max_pen = JAIL_BAIL;		break;
  case CRIME_NORMAL:
    max_pen = JAIL_EXTENDED;		break;
  case CRIME_HEAVY:
    max_pen = JAIL_EXECUTE;		break;
  case CRIME_DEATH:
    max_pen = JAIL_EXECUTE;		break;
  default:
    max_pen = JAIL_NORMAL;		break;
  }
  
  /* outlaws always get the cut */
  if (IS_OUTLAW(victim)){
    crime = CRIME_DEATH;
    max_pen = JAIL_EXECUTE;
  }

  if ( crime == CRIME_DEATH || ch == victim){
    if( (paf = set_sentence(victim, max_pen, number_range(1, 5))) == NULL)
      send_to_char("`!An error occured, contact an immortal.``\n\r", ch);
    else
      string_to_affect(paf, ch == victim ? "surrendered" : ch->name);
  }
  else if( (paf = set_sentence(victim, JAIL_NORMAL, 1)) == NULL)
    send_to_char("`!An error occured, contact an immortal.``\n\r", ch);
  else
    string_to_affect(paf, ch == victim ? "surrendered" : ch->name);
  
  
  /* Yell out the announcement */
  if (ch == victim)
    sprintf(buf, "Justice be praised, %s has surrendered to Justice!",
	    PERS2(victim));
  else
    sprintf(buf, "Justice be praised, %s has been captured by %s!",
	    PERS2(victim), PERS2(ch));
  jail_announce(jail_cell_lookup(victim->in_room->vnum), buf);

  /* increase capture count if ch != victim */
  if (ch != victim
      && ch->pCabal 
      && IS_CABAL(ch->pCabal, CABAL_JUSTICE)){
    ch->pcdata->member->kills++;
  }
}



/* Written by: Virigoth							*
 * Returns: Void							*
 * Used: effect.c,							*
 * Comment: Transports the character out of the jail cell into the room *
 * dictated by "guardhouse" in jail_table					*/

void unjail_char(CHAR_DATA* ch){

  ROOM_INDEX_DATA* room;
  CHAR_DATA* wch;
  AFFECT_DATA* paf;

  char buf[MIL];
  int jail = 0;
  int exit = 0;

  /* check for problems */
  if (!ch){
    bug("unjail_char: NULL ch passed.", 0);
    return;
  }

  if (IS_NPC(ch)){
    bug("unjail_char: ch NPC passed.", 0);
    return;
  }

  /* check that char. is in a cell */
  if (!IS_SET(ch->in_room->room_flags2, ROOM_JAILCELL))
    bug("unjail_char: ch not in room marked ROOM_JAILCELL", 0);

  /* check for exit out of the jail */
  jail = jail_cell_lookup(ch->in_room->vnum);
  exit = jail_table[jail].guardhouse;

  /* if exit is 0 we send to home temple */
  if ( (room = get_room_index(exit))  == NULL){
    char buf[MIL];
    sprintf(buf, "unjail_char: room %d does not exist as an exit.", 
	    exit);
    bug(buf, 0);
  }
  if (!room)
    room = get_room_index(get_temple(ch));
  if (room == NULL){
    send_to_char("You are completely lost.\n\r",ch);
    return;
  }
  /* Yell out the announcement */
  sprintf(buf, "The sentence served, %s is now free and innocent!", PERS2(ch));
  jail_announce(jail, buf);

  /* move the char out of jail*/
  char_from_room(ch);
  char_to_room(ch, room);
  act("The guards escort $n into the area and release $m.", ch, NULL, NULL, TO_ROOM);
  do_look(ch, "auto");
  /* get rid of flag */
  if (!IS_OUTLAW( ch )){
    REMOVE_BIT(ch->act, PLR_WANTED);
  }

  /* broadcast on justice channel */
  for ( wch = char_list; wch != NULL; wch = wch->next ){
    if ( IS_NPC(wch) && IS_SET(wch->off_flags,CABAL_GUARD)
	 && wch->pIndexData->group == VNUM_JUSTICE ){
      REMOVE_BIT(wch->comm,COMM_NOCHANNELS);
      REMOVE_BIT(wch->comm,COMM_NOCABAL);
      do_jcabaltalk(wch, buf);
      SET_BIT(wch->comm,COMM_NOCABAL);
      SET_BIT(wch->comm,COMM_NOCHANNELS);
      break;
    }
  }//END CABAL CHANNEL TALK
  /* small check */
  if ( (paf = affect_find(ch->affected, gen_jail)) != NULL){
    paf->modifier = JAIL_NONE;
    affect_strip(ch, gen_jail);
  }
  //set wanted to expire
  for (paf = ch->affected; paf; paf = paf->next){
    if (paf->type == gsn_wanted)
      paf->duration = 0;
  }
  //  affect_strip( ch, gsn_wanted );
}





/* Written by: Virigoth							*
 * Returns: Void							*
 * Used: effect.c,							*
 * Comment: Command which lets the justice dictate fate of prisoner.    *
 * only the justice matching the string passed in gen_jail can affect   *
 * the prisoner, and only if prisoner is stillin a ROOM_JAILCELL room.  */

void do_jail( CHAR_DATA *ch, char *argument ){
  /*
    jail <criminal> <sentence> <severity/type of execution>


SENTENCE FLOW:  (NORMAL SET ON CAPTURE OR DEATH FOR ATTORICTY CRIMES)

	     /-> JAIL_TRANSFER
	    /--> JAIL_BAIL -> JAIL_EXTEND-> JAIL_RELEASE
JAIL_NORMAL ---> JAIL_EXTEND -> JAIL_RELEASE
	    \--> JAIL_EXECUTE
	     \-> JAIL_RELEASE
  */

  CHAR_DATA* victim;	//criminal
  CHAR_DATA* justice;	//Owner of criminal
  CHAR_DATA* vch;

  AFFECT_DATA* paf;	//Info from gen_jail (if not found, abort)

  BUFFER *buffer;	//For display of criminals

  char arg1[MIL];	//Target criminal
  char arg2[MIL];	//Sentence
  char buf[MIL];

  int count = 0;

  int cur_sen = JAIL_NORMAL;
  int new_sen = JAIL_NORMAL;
  int new_sev = 1;
  int max_pen = JAIL_BAIL;

  bool fAllow = TRUE;	//used tocheck if sentence flow is allowed

  if (!ch->pCabal || !IS_CABAL(ch->pCabal, CABAL_JUSTICE))
    return;

  /* first check for null to show syntax  mates */
  if (argument[0] == '\0'){
    sendf(ch, "Syntax: jail <criminal> <sentence> <severity (1-10)>\n\r"\
	  "for <sentence> of bail, amount is %d x severity gold with limit of %dh\n\r"\
	  "for <sentence> of extended, length is %d + (%d x severity) hours\n\r\n\r"\
	  "Following are all criminals with their jurisdictions:\n\r", 
	  SEV_BAIL, DUR_BAIL, DUR_EXTENDED, SEV_EXTENDED);
    /* run through players showing info */
    buffer=new_buf();
    for (vch = player_list; vch; vch = vch->next){
      /* count only those in cells and still wanted*/
      if (!IS_SET(vch->act, PLR_WANTED)|| !vch->in_room
	  || !IS_SET(vch->in_room->room_flags2, ROOM_JAILCELL))
      continue;
      /* check for gen_jail with justice name */
      if ( (paf = affect_find(vch->affected, gen_jail)) == NULL
	   || !paf->has_string)
      continue;
      /* add info to buffer */
      sprintf(buf, "%d. %-5s %-15s in %-10s assigned to %-15s [%-2s (%dh)]\n\r",++count, PERS2(vch), 
	      vch->in_room->area->name, vch->in_room->name, paf->string,
	      paf->modifier == JAIL_NONE ? "None" : 
	      paf->modifier == JAIL_NORMAL ? "Normal" : 
	      paf->modifier == JAIL_EXTENDED ? "Extended" : 
	      paf->modifier == JAIL_BAIL ? "Bail" : 
	      paf->modifier == JAIL_EXECUTE ? "Execution" : 
	      paf->modifier == JAIL_RELEASE ? "Release" : "Error", 
	      paf->duration);


      add_buf( buffer, buf );
    }
    /* check if anything found */
    if (!count)
      send_to_char("The jails are empty.\n\r", ch);
    else
      page_to_char(buf_string(buffer),ch);
    free_buf(buffer);
    return;
  }
    
    

  /* start testing the actual arguments */
  argument = one_argument( argument, arg1 );
  argument = one_argument( argument, arg2 );

  if ( (victim = get_char(arg1)) == NULL || IS_NPC(victim)){
    send_to_char("No such player found.\n\r", ch);
    return;
  }

  /* check they are criminal and justice have jurisdiction */
  if ( (!IS_SET(victim->act, PLR_WANTED)|| !victim->in_room
	|| !IS_SET(victim->in_room->room_flags2, ROOM_JAILCELL))
       && !IS_IMMORTAL(ch)){
    send_to_char("The target player must be [`1WANTED``] and be in a jailcell.\n\r", ch);
    return;
  }

  if ( (paf = affect_find(victim->affected, gen_jail)) == NULL){
    send_to_char("That player is not affected by any type of incarceration.\n\r", ch);
    return;
  }
  else if (!paf->has_string || !is_name(paf->string, ch->name)){
    if (!IS_IMMORTAL(ch)){
      send_to_char("You do not have jurisdiction over that criminal.\n\r", ch);
      return;
    }
  }

  if (arg2[0] == '\0'
      || (str_cmp("bail", arg2)
      && str_cmp("extend", arg2)
      && str_cmp("execute", arg2)
      && str_cmp("release", arg2)
      && str_cmp("transfer", arg2))){
    send_to_char("The sentence must be one of following:\n\r"\
		 "bail, extend, execute, release, transfer\n\r", ch);
    return;
  }

  /* get the maximum penalty based on "wanted" effect */
  switch (show_crimes( ch, victim, FALSE, TRUE ) ){
  case CRIME_LIGHT:
    max_pen = JAIL_BAIL;		break;
  case CRIME_NORMAL:
    max_pen = JAIL_EXTENDED;		break;
  case CRIME_HEAVY:
    max_pen = JAIL_EXECUTE;		break;
  case CRIME_DEATH:
    max_pen = JAIL_EXECUTE;		break;
  }

  /* select action and check over severities*/
  if (!str_cmp("bail", arg2)){
    new_sen = JAIL_BAIL;
    if (!(new_sev = atoi(argument))
	|| new_sev > 10){
      send_to_char("Severity must be on scale 1-10", ch);
      return;
    }
  }
  else if (!str_cmp("extend", arg2)){
    new_sen = JAIL_EXTENDED;
    if (!(new_sev = atoi(argument))){
      send_to_char("Severity must be on scale 1-10", ch);
      return;
    }
  }
  else if (!str_cmp("execute", arg2)){
    new_sen = JAIL_EXECUTE;
    if ( (new_sev = jexecution_lookup(argument)) == 0){
      int i = 0;
      send_to_char("Following are valid executions:\n\r", ch);
      for (i = 0; execution_table[i].name != NULL; i++){
	if (!execution_table[i].name[0])
	  continue;
	sendf(ch, "%s\n\r", execution_table[i].name);
      }
      return;
    }
  }
  else if (!str_cmp("release", arg2))
    new_sen = JAIL_RELEASE;
  else if (!str_cmp("transfer", arg2))
    new_sen = JAIL_TRANSFER;
  else{
    sprintf(buf, "do_jail: Sentence %s not found or not valid.", arg2);
    bug(buf, 0);
    send_to_char(buf, ch);
    return;
  }

  /* check if the sentence selected is not over max */
  if (new_sen > max_pen ){
    act("That sentence is too severe based on the crimes $N has commited.", ch, NULL, victim, TO_CHAR);
    return;
  }
  /* All checks are clear, we now make sure that the SENTENCE flow is satisfied */   
  cur_sen = paf->modifier;

  switch (cur_sen){
  default:
  case JAIL_RELEASE:
  case JAIL_TRANSFER:
  case JAIL_EXECUTE:
    fAllow = FALSE;
    break;
  case JAIL_EXTENDED:
    if (new_sen != JAIL_RELEASE
	&& new_sen != JAIL_TRANSFER)
      fAllow = FALSE;
    break;
  case JAIL_BAIL:
    if (new_sen != JAIL_TRANSFER)
      fAllow = FALSE;
    break;
  case JAIL_NORMAL:
    break;
  }


  if (!fAllow){
    send_to_char("This new verdict is not allowed due to criminals current sentence.\n\r", ch);  
    return;
  }

  /* change verdict */
  if (new_sen == JAIL_TRANSFER){
    if ( (justice = get_char(argument)) == NULL){
      send_to_char("No such player found.\n\r", ch);
      return;
    }

    if (justice == ch){
      send_to_char("You already have jurisdiction over that criminal.\n\r", ch);
      return;
    }
    if (!justice->desc || ch->in_room->vnum == ROOM_VNUM_LIMBO){
      send_to_char("Their soul seemed to vacate the body for now.\n\r", ch);
      return;
    }

    if (IS_NPC(justice) || justice->pCabal == NULL 
	|| !IS_CABAL(justice->pCabal, CABAL_JUSTICE)){
      send_to_char("That person is not a Justice member.\n\r", ch);
      return;
    }
    /* change the name of Justice in charge */
    string_to_affect(paf, justice->name);
    act("You have given $N jurisdiction over $t.", ch, PERS2(victim), justice, TO_CHAR);
    act("$n has given you jurisdiction over $t.", ch, PERS2(victim), justice, TO_VICT);
    act("Jurisdiction over your sentance has just been handed to $N.", victim, NULL, justice, TO_CHAR);
    return;
  }
  /* change sentance */
  set_sentence(victim, new_sen, new_sev);
  act_new("$N's new sentence has been set.", ch, NULL, victim, TO_CHAR, POS_DEAD);
}



/* Written by: Virigoth							*
 * Returns: Void							*
 * Used: effect.c,							*
 * Comment: Performs the actual execution and creates an object EXECUTION*
 * as a marker, which decays after "decay" ticks. The periodic yells are*
 * done by gen. Execution performed based on current Jailcell location	*/
void jail_execute(CHAR_DATA* ch, CHAR_DATA* mob, int exe_type, char* name){

  ROOM_INDEX_DATA* room;
  AFFECT_DATA* crime;
  OBJ_DATA* obj, *bag, *tattoo;
  CHAR_DATA *vch, *vch_next;
  char crime_str[MIL], strsave[MIL];
  int crimes = 0;
  char buf[MIL];
  int jail = 0;
  int exit = 0;
  
  const int dur = 480;

  /* check for problems */
  if (!ch){
    bug("jail_execute: NULL ch passed.", 0);
    return;
  }
  if (IS_NPC(ch)){
    bug("jail_execute: NPC ch passed.", 0);
    return;
  }
  /* check that char. is in a cell */
  if (!IS_SET(ch->in_room->room_flags2, ROOM_JAILCELL))
    bug("jail_execute: ch not in room marked ROOM_JAILCELL", 0);

  jail = jail_cell_lookup(ch->in_room->vnum);
  exit = jail_table[jail].exe_room;
  
  /* if exit is 0 we send to home temple */
  if ( (room = get_room_index(exit))  == NULL){
    char buf[MIL];
    sprintf(buf, "jail_execute: room %d does not exist as an exe_room.", 
	    exit);
    bug(buf, 0);
  }
  if (!room)
    room = get_room_index(get_temple(ch));
  if (room == NULL){
    send_to_char("You are completely lost.\n\r",ch);
    return;
  }
  /* move the char out of jail, announce */
  char_from_room(ch);
  char_to_room(ch, room);
  act("The guards escort $n into the area.", ch, NULL, NULL, TO_ROOM);
  do_look(ch, "auto");
  /* Announce one last time */
/* we make a bitvector of all the cimes the person has commited */
  for (crime = ch->affected; crime != NULL; crime = crime->next){
    if (crime->type == gsn_wanted && crime->bitvector != 0){
      crimes |= crime->bitvector;
    }
  }
  sprintf( crime_str, "For the crimes of " );
  if (IS_SET(crimes, CRIME_FLAG_S)){
    strcat( crime_str, "Not sheathing" );
    strcat( crime_str, ", ");
  }
  if (IS_SET(crimes, CRIME_FLAG_L)){
    strcat( crime_str, crime_table[CRIME_LOOT].name );
    strcat( crime_str, ", ");
  }
  if (IS_SET(crimes, CRIME_FLAG_T)){
    strcat( crime_str, crime_table[CRIME_THEFT].name );
    strcat( crime_str, ", ");
  }
  if (IS_SET(crimes, CRIME_FLAG_A)){
    strcat( crime_str, crime_table[CRIME_ASSAULT].name );
    strcat( crime_str, ", ");
  }
  if (IS_SET(crimes, CRIME_FLAG_M)){
    strcat( crime_str, crime_table[CRIME_MURDER].name );
    strcat( crime_str, ", ");
  }
  if (IS_SET(crimes, CRIME_FLAG_O)){
    strcat( crime_str, crime_table[CRIME_OBSTRUCT].name );
    strcat( crime_str, ", ");
  }
  
  sprintf(buf, "%sby the Law of Aabahran,\n\r"\
	  "%s has been sentenced by %s %s\n\r"\
	  "May Virigoth have mercy on your soul %s.", 
	  crime_str,
	  PERS2(ch), IS_NULLSTR(name) ? "Justice" : name,
	  execution_table[exe_type].announce,
	  PERS2(ch));
  jail_announce(jail, buf);
  
  /* show the TOVICT messages from the table*/
  act(execution_table[exe_type].pre_act, mob, NULL, ch, TO_CHAR);
  act(execution_table[exe_type].on_act_r, mob, NULL, ch, TO_NOTVICT);
  act(execution_table[exe_type].on_act_c, mob, NULL, ch, TO_VICT);

  /* create bag with stuff (NULL if no bag, or no stuff to bag)*/
  bag = create_jailbag(mob, ch, FALSE, TRUE);
  
  /* get rid of flag */
  if (!IS_OUTLAW( ch ))
    REMOVE_BIT(ch->act, PLR_WANTED);
  affect_strip( ch, gsn_wanted );

  /* give penalty */
  if (!IS_OUTLAW( ch ))
    ch->exp -= UMIN(6000,UMIN(exp_per_level(ch,ch->level),ch->exp/10));
  
  /* create the object */
  obj = create_object( get_obj_index( OBJ_VNUM_EXECUTION ), 0);
  free_string(obj->description);
  sprintf(buf, execution_table[exe_type].room_desc, PERS2(ch));
  obj->description = str_dup( buf );
  obj->timer = dur;
  obj_to_room(obj, room);

  /* broadcast on justice channel */
  sprintf(buf, "%s has been executed by %s as per %s's orders.  The Justice prevails!", PERS2(ch), PERS2(mob), IS_NULLSTR(name) ? "Justice" : name);
  cabal_echo_flag( CABAL_JUSTICE, buf );
  

  /* slay him */
  sprintf( log_buf, "`&%s executed at %s [room %d]``",
	   ch->name,
	   ch->in_room->name, 
	   ch->in_room->vnum);
  
  nlogf( log_buf );
  wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0);
  ch->pcdata->dall++;
  ch->pcdata->dpc++;
  mud_data.deaths++;

  stop_fighting( ch, TRUE );
  if (!IS_NPC(ch) && IS_SET(ch->act, PLR_DOOF))
    REMOVE_BIT(ch->act, PLR_DOOF);
  death_cry( ch, mob );

  for ( vch = char_list; vch != NULL; vch = vch_next ){
    vch_next = vch->next;
    if (IS_NPC(vch) && vch->hunting != NULL && vch->hunting == ch ){
      vch->hunting = NULL;
      if (IS_SET(vch->act,ACT_AGGRESSIVE))
	{
	  act( "$n slowly disappears.",vch,NULL,NULL,TO_ROOM );
	  extract_char( vch, TRUE );
	}
    }
  }
  sendf(ch, "\n\rAs the cold chill of death descends upon you %s grants you yet another chance.\n\r"\
	"You have been granted a temporary sanctuary as an invincible ghost.\n\rAs long as you don't attack"\
	" anything.\n\r", (ch->pcdata->deity[0] == '\0' ?  "The Creator" : ch->pcdata->deity));

  tattoo = get_eq_char(ch, WEAR_TATTOO);
  if (tattoo != NULL) 
    obj_from_char(tattoo);   

  extract_char( ch, FALSE );

  if (tattoo != NULL) 
    {
      obj_to_char(tattoo, ch); 
      equip_char(ch, tattoo, WEAR_TATTOO); 
    }

  /* move the bag to ex-criminal */
  if (bag){
    obj_from_char(bag);
    obj_to_char(bag, ch);
  }

  /* Destory the mob */
  char_from_room(mob);
  extract_char(mob, TRUE);

  
  ch->position	= POS_STANDING;
  ch->hit		= 1;
  ch->mana	= 1;
  ch->move	= UMAX( 100, ch->move );

  ch->pcdata->ghost = time(NULL);
  ch->pcdata->fight_delay = time(NULL);
  ch->pcdata->pk_delay = time(NULL);
  ch->pcdata->condition[COND_HUNGER]=48;
  ch->pcdata->condition[COND_THIRST]=48;
  if (!IS_NPC(ch) && ch->pcdata->familiar != NULL){
    extract_char( ch->pcdata->familiar, TRUE );
    ch->pcdata->familiar=NULL;
  }
  if (ch->pcdata->dall > 60 && get_trust(ch) < MASTER){
    send_to_char("You have died due to failing health.\n\r",ch);
    sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( ch->name ) );
    wiznet("$N dies due to failing health.",ch,NULL,0,0,0);
    ch->pcdata->dall = 0;
    if (ch->level > 20)
      deny_record(ch);
    if (ch->pCabal){
      CABAL_DATA* pCab = ch->pCabal;
      update_cabal_skills(ch, ch->pCabal, TRUE, TRUE);
      char_from_cabal( ch );
      CHANGE_CABAL(pCab);
      save_cabals( TRUE, NULL );
    }  
    if (ch->pcdata->pbounty){
      rem_bounty( ch->pcdata->pbounty );
      free_bounty( ch->pcdata->pbounty );      
    }
    extract_char( ch, TRUE );
    if ( ch->desc != NULL )
      close_socket( ch->desc );
    unlink(strsave);
    return;
  }
  if (ch->perm_stat[STAT_CON] > 3){
    if (ch->pcdata->dall%5 == 0)
      {
	ch->perm_stat[STAT_CON]--;
	send_to_char("You feel less healthy.\n\r",ch);
      }
  }
  /* Cabal Requip */
  save_char_obj( ch );
}


/* Written by: Virigoth							*
 * Returns: Void							*
 * Used: jail.c,interp.c						*
 * Comment: Allows to pay the bribe to current justice overseeing char. 
 * if justice is not present, gold is deducted but not deposited anywhere */
void do_bail( CHAR_DATA *cha, char *argument ){
  /* bail <target> <gold/cp>, if <target> is "gold" or "cp" is ignored */

  AFFECT_DATA* paf;
  CHAR_DATA* justice;
  CHAR_DATA* ch = cha;

  char arg1[MIL];

  int bail = 0;
  int assets = 0;

  bool fGold = FALSE;

  argument = one_argument(argument, arg1);
  /* select between paying for self, or other */
  if (arg1[0] != '\0' && str_cmp("gold", arg1) 
      && str_cmp("cp", arg1)){
    if ( (ch = get_char_world(cha, arg1)) == NULL){
      send_to_char("You cannot locate them.\n\r", cha);
      return;
    }
    if (IS_NPC(ch)){
      send_to_char("Pay bail for a mob?  What a grand idea!\n\r", cha);
      return;
    }
  }

  /* now "ch" is proper target */
  /* check if affected by bail */

  if ( (paf = affect_find(ch->affected, gen_jail)) == NULL
       || paf->modifier != JAIL_BAIL){
    send_to_char("There is no need or no possibility of paying bail.\n\r", cha);
    return;
  }
  /* calculate bail */
  bail = paf->level * SEV_BAIL;

  /* check for latter arguments (no gold/cp argument)*/
  if (ch == cha){
    if (arg1[0] == '\0'){
      /* Cabaled char's get to pay with cp too */
      if (!ch->pCabal)
	sendf(cha, "Your bail has been set at %d, use \"bail gold\" to pay.\n\r", bail);
      else
	sendf(cha, "Your bail has been set at %d Gp or %d Cp, use \"bail <gold/cp>\" to pay.\n\r", bail, bail / 100);
    return;
    }
    else if (!str_cmp("gold", arg1)){
      assets = ch->in_bank + ch->gold;
      fGold = TRUE;
    }
    else if (!str_cmp("cp", arg1)){
      assets = GET_CP(ch);
      bail /= 100;
    }
    else{
      send_to_char("Bail <criminal> <gold/cp>\n\rBail <gold/cp>\n\r", cha);
      return;
    }
  }
  else{
    if (argument[0] == '\0'){
      /* Cabaled char's get to pay with cp too */
      if (!ch->pCabal)
	sendf(cha, "Their bail has been set at %d, use \"bail gold\" to pay.\n\r", bail);
      else
	sendf(cha, "Their bail has been set at %d Gp or %d Cp, use \"bail <gold/cp>\" to pay.\n\r", bail, bail / 100);
      return;
    }
    else if (!str_cmp("gold", argument)){
      assets = ch->in_bank + ch->gold;
      fGold = TRUE;
    }
    else if (!str_cmp("cp", argument)){
      assets = GET_CP(ch);
      bail /= 100;
    }
    else{
      send_to_char("Bail <criminal> <gold/cp>\n\rBail <gold/cp>\n\r", cha);
      return;
    }
  }

/* check our account */
if (assets < bail){
    sendf(cha ,"Your total assets are %d (%s) which is not enough to pay the bail of %d (%s).\n\r",
	  assets, fGold ? "gold" : "cp" , bail, fGold ? "gold" : "cp");
    return;
  }
  if (fGold){
    /* start withdrawing */
    cha->in_bank -= bail;
    if (cha->in_bank < 0){
      cha->gold += cha->in_bank;
      cha->in_bank= 0;
    }
    sendf(cha, "Your bank balance is %d, you have %ld gold left on you.\n\r", cha->in_bank, cha->gold);
  }
  else
    CP_GAIN(cha, -bail, TRUE);

  if ( (justice = get_char(paf->string)) == NULL)
    return;

  unjail_char(ch);  

  /* give justice gold */
  if (fGold){
    justice->in_bank += bail;
    sendf(justice, "%s has paid the bail. Your bank balance is: %d.\n\r", PERS2(ch), justice->in_bank);
  }else
    CP_GAIN(justice, bail, TRUE);
}


/* Written by: Virigoth							*
 * Returns: TRUE if cells have power					*
 * Used: jail.c, act_move.c						*
 * Comment:Compares the vnum of room passed to jail_table for match of  *
 * cell. If match is made, checks [].guardhouse for any mob marked	*
 * "guild_guard", if found returns TRUE, if not, FALSE			*/
bool jail_check(ROOM_INDEX_DATA* room){
  CHAR_DATA* vch;
  ROOM_INDEX_DATA* enter;
  int jail = jail_cell_lookup(room->vnum);

  /* try to get index to guardhouse */
  if ( (enter = get_room_index(jail_table[jail].guardhouse)) == NULL){
    char buf[MIL];
    sprintf(buf ,"jail_check: Jail guardhouse %d could not be found.", 
	    jail_table[jail].guardhouse);
    bug(buf, 0);
    return FALSE;
  }

  /* all we do is check the guardhouse for cabal_guard */
  for (vch = enter->people; vch; vch = vch->next_in_room){
    if (IS_NPC(vch) && IS_SET(vch->off_flags, GUILD_GUARD))
      return TRUE;
  }
  return FALSE;
}


/* Written by: Virigoth							*
 * Returns: void							*
 * Used: jail.c, act_move.c						*
 * Comment: If ch is in powered jailcell and has no gen_jail, gsn_judge *
 * is applied with increasing modifier.  Past certain point (max_mod)	*
 * ch is teleported out of jail, and will not be able to pass jail fields*
 * if fGain == TRUE we only check gain the the affect (vtick) FALSE we	*
 * check lowering of the affect (tick)
 * This is run once per 3 sec (10 x Tick).				*/
void jail_abuse_check(CHAR_DATA* ch, bool fGain){
  AFFECT_DATA* paf, af;

  int mod = 0;

  const int ratio = ABUSE_RATIO;	//ratio of time in CELL : OUTSIDE
  const int max_mod = ABUSE_KICK; //How many iterations before being kicked
				  //if in a cell. (10 per tick)

  /* check if this is gain and we are in a cell */
  if (fGain && !IS_SET(ch->in_room->room_flags2, ROOM_JAILCELL))
    return;
  /* check if this is an inmate */
  if (IS_IMMORTAL(ch) || IS_NPC(ch) || IS_WANTED(ch) || is_affected(ch, gen_jail))
    return;

  /* check if affect exists */
  if ( (paf = affect_find(ch->affected, gsn_judge)) != NULL)
    mod = paf->modifier;

  /* check if in jailcell if its powered we add */
  if (IS_SET(ch->in_room->room_flags2, ROOM_JAILCELL)
      && jail_check(ch->in_room))
    mod += ratio;
  else if (!fGain)
    mod -= PULSE_TICK / PULSE_VIOLENCE;
  else
    mod --;
  
  /* safety */
  mod = URANGE(-1, mod, 3000);

  /* add on or apply the mod */
  if (!paf){
    af.type = gsn_judge;
    af.level = 1;
    af.duration = -1;
    af.where = TO_NONE;
    af.bitvector = 0;
    af.location = APPLY_NONE;
    af.modifier = mod;
    if (mod > 0)
      affect_to_char(ch, &af);
    return;
  }
  else
    paf->modifier = mod;

  /* check if we should kick them out */
  if (mod > max_mod){
    AFFECT_DATA* paf;
    ROOM_INDEX_DATA* room;
    int jail = jail_cell_lookup(ch->in_room->vnum);
    int exit = jail_table[jail].guardhouse;

    /* if exit is 0 we send to home temple */
    if ( (room = get_room_index(exit))  == NULL){
      char buf[MIL];
      sprintf(buf, "jail_abuse_check: room %d does not exist as an exit.", 
	      exit);
      bug(buf, 0);
    }
    if (!room)
      room = get_room_index(get_temple(ch));
    if (room == NULL){
      send_to_char("You are completely lost.\n\r",ch);
      return;
    }
    /* we have the room, so we move them */
    act("A squad of guards surrounds the cell and quicly escort $n out.", ch, NULL, NULL, TO_ROOM);
    act("A squad of guards surrounds the cell and quicly escort you out.", ch, NULL, NULL, TO_CHAR);
    char_from_room(ch);
    char_to_room(ch, room);
    act("A squad of jail guards escort $n in and leave.", ch, NULL, NULL, TO_ROOM);
    do_look(ch, "auto");
    /* decreae the modifier byone ratio at least so we dont get double transport */
    if ( (paf = affect_find(ch->affected, gsn_judge)) != NULL)
      paf->modifier = UMAX(0, paf->modifier - ABUSE_RATIO);
  }//END kick out
  else if (mod < 1)
    affect_strip(ch, gsn_judge);
}
    
/* checks if a given crime in given room is a crime */
bool is_crime( ROOM_INDEX_DATA* room, int crime, CHAR_DATA* victim){
  if (room == NULL || crime >= MAX_CRIME)
    return FALSE;
  else if (!IS_SET(room->area->area_flags, AREA_LAWFUL))
    return FALSE;
  else if (victim && IS_NPC(victim) && IS_SET(victim->act, ACT_RAIDER))
    return FALSE;
  else if (victim && victim->pCabal && IS_CABAL(victim->pCabal, CABAL_JUSTICE))
    return TRUE;
  else if (room->area->crimes[crime] != 0)
    return TRUE;
  else
    return FALSE;
}

/* marks a given character for a given crime using the "Wanted" skill */
/* information is stored in a seperate wanted effect for each city
   crimes commited	: bitvector
   city			: location
   times flagged	: modifier (if its none zero then the crime has not been flagged for yet)

*/
AFFECT_DATA* set_crime( CHAR_DATA* ch, CHAR_DATA* victim, AREA_DATA* area, int crime){
  int dur = 1440;
  AFFECT_DATA* paf;
  CHAR_DATA* vch;
  int city = 0;
  bool fJustice = FALSE;

  if (ch == NULL || IS_NPC(ch) || area == NULL || crime >= MAX_CRIME)
    return NULL;
  else{
    city = area->vnum;
    dur = URANGE(1, ch->pcdata->flagged, 10) * dur / 10;
  }

  if (area->pCabal != NULL && IS_AREA(area, AREA_CABAL) && IS_CABAL(area->pCabal, CABAL_JUSTICE))
    fJustice = TRUE;

  /* don't bother if victim is wanted and attack is justice */
  if (!fJustice && ch->pCabal && IS_CABAL(ch->pCabal, CABAL_JUSTICE) && victim && IS_WANTED(victim))
    return NULL;

  //if in justice cabal we do not need to check
  /* run through the area checking if there are justice about */
  for (vch = player_list; vch; vch = vch->next_player){
    if (!IS_NPC(vch) && vch->desc && vch->in_room->area == area
	&& vch->pCabal 
	&& (IS_CABAL(vch->pCabal, CABAL_JUSTICE) || IS_HIGHBORN(ch))
	&& !IS_AFFECTED(vch, AFF_INVISIBLE)
	&& !IS_AFFECTED(vch, AFF_HIDE)
	&& !IS_AFFECTED2(vch, AFF_CAMOUFLAGE))
      break;
  }
  if (!fJustice && vch == NULL){
    /* run through cabals check if justice parent cabal has any players in it */
    CABAL_DATA* pCab;
    for (pCab = cabal_list; pCab; pCab = pCab->next){
      if (!IS_CABAL(pCab, CABAL_JUSTICE) || pCab->parent)
	continue;
      if (pCab->present < 1)
	continue;
      else
	break;
    }
    /* the crime was not spotted, we affect the relation ships adversly */
    if (area->pCabal && pCab)
      affect_justice_relations( area->pCabal, -5 );
    return NULL;
  }
  /* we run through all the pafs on the character looking wanted 
     with given city 
  */

  for (paf = ch->affected; paf; paf = paf->next){
    if (paf->type == gsn_wanted && paf->location == city)
      break;
  }

  /* now we either have a paf or not */
  if (paf == NULL){
    AFFECT_DATA af;

    af.type	=	gsn_wanted;
    af.duration	=	dur;
    af.level	=	60; 
    
    af.where	=	TO_NONE;
    af.bitvector=	0;
    af.location	=	city;
    //new crime, will be put into bitvector when wanted.
    if (victim && victim->pCabal && IS_CABAL(victim->pCabal, CABAL_JUSTICE))
      af.modifier =	crime_table[CRIME_OBSTRUCT].bit; 
    else
      af.modifier =	crime_table[crime].bit; 
    
    paf = affect_to_char( ch, &af);
  }
  else{
/* we update an existing crime info for a city */
    paf->modifier	|= crime_table[crime].bit; //add this crime to the ones waiting to be put in bitvector when wanted
    paf->duration	= dur;
  }
  affect_strip(ch, gsn_timer );
  return paf;
}

/* shows the crimes victim has been flagged for, and returns the maximum penalty */
int show_crimes( CHAR_DATA* ch, CHAR_DATA* victim, bool fPunish, bool fPenOnly ){
  char buf[MSL];
  char buf2[MIL];
  AFFECT_DATA* paf;
  AREA_DATA* pArea;

  int max_pen = CRIME_ALLOW;

  buf[0] = '\0';
  for (paf = victim->affected; paf; paf = paf->next){
    if ( paf->type == gsn_wanted && paf->bitvector != 0
	 && (pArea = get_area_data( paf->location )) != NULL){
      bool fFirst = TRUE;
      int i = 0;
      /* we run through all crimes making a list */
      for (i = 0; i < MAX_CRIME; i++){
	if (!IS_SET(paf->bitvector, crime_table[i].bit))
	  continue;
	if (fFirst){
	  sprintf(buf2, "%-15s (%2dd): %-10s %s%s%s\n\r",
		  pArea->name,
		  paf->duration / 24,
		  crime_table[i].name,
		  fPunish ? "(" : "",
		  fPunish ? punish_table[pArea->crimes[i]].name : "",
		  fPunish ? ")" : "");
	  fFirst = FALSE;
	}
	else{
	  sprintf(buf2, "%-20s : %-10s %s%s%s\n\r",
		  "",
		  crime_table[i].name,
		  fPunish ? "(" : "",
		  fPunish ? punish_table[pArea->crimes[i]].name : "",
		  fPunish ? ")" : "");
	}
	strcat( buf, buf2 );
	/* select the highest penalty */
	if (punish_table[pArea->crimes[i]].bit > max_pen)
	  max_pen = punish_table[pArea->crimes[i]].bit;
      }
    }
  }

  if (IS_NULLSTR(buf) || fPenOnly)
    return max_pen;
  else if ( ch == victim )
    send_to_char("You are wanted for following crimes:\n\r", ch);
  else
    sendf( ch, "%s is wanted for following crimes:\n\r", PERS2( victim ));
  send_to_char( buf, ch );
  return max_pen;
}
	  
/* returns an integer representing a crime or -1 */
int crime_lookup (const char *name ){
    int crime;
    for (crime = 0; crime_table[crime].name != NULL; crime++){
      if (LOWER(name[0]) == LOWER(crime_table[crime].name[0]) && !str_prefix(name, crime_table[crime].name))
	return crime;
    }
    return -1;
}