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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <malloc.h>
#include "merc.h"
#include "recycle.h"
#include "bounty.h"
#include "cabal.h"
#include "interp.h"
#include "jail.h"
#include "save_mud.h"

/***************************************************************/
/*Following are bounty orientanted routines for Forsaken Lands  */
/*mud created by Virigoth circa 2002.  Copyrighted for Forsaken*/
/*Lands mud June 1, 2002.  Do not use or copy without explicit */
/*permission of author. (Voytek Plawny aka Virigoth)	       */
/***************************************************************/


extern PACT_DATA* pact_list;
/* global bounty list */
BOUNTY_DATA* bounty_list = NULL;


/* attatches an objec to a bounty bid and puts it in a bounty room */
void obj_to_bbid( OBJ_DATA* obj, BBID_DATA* bbid ){
  
  if (obj == NULL || bbid == NULL)
    return;
  else if (obj->in_room )
    obj_from_room( obj );
  else if (obj->carried_by)
    obj_from_char( obj );
  else if (obj->in_obj )
    obj_from_obj ( obj );
  else if (obj->bbid )
    obj_from_bbid( obj );

  if (bbid->obj == NULL){
    bbid->obj = obj;
    bbid->obj->next_bidobj = NULL;
  }
  else{
    obj->next_bidobj = bbid->obj;
    bbid->obj = obj;
  }

  obj_to_room( obj, get_room_index( ROOM_VNUM_BOUNTY ));
  obj->bbid = bbid;
}

/* removes an object from bounty room and the bid list */
void obj_from_bbid( OBJ_DATA* obj ){
  BBID_DATA* bbid = obj->bbid;

  if (bbid == NULL){
    bug("obj_from_bbid: obj has no bounty bid.", 0);
    return;
  }
  if (obj->in_room && obj->in_room->vnum == ROOM_VNUM_BOUNTY )
    obj_from_room( obj );
  
  if ( obj == bbid->obj )
    bbid->obj = obj->next_bidobj;
  else{
    OBJ_DATA *prev;
    for ( prev = bbid->obj; prev; prev = prev->next_bidobj ){
      if ( prev->next_bidobj == obj ){
	prev->next_bidobj = obj->next_bidobj;
	break;
      }
    }
    if ( prev == NULL ){
      bug( "Obj_from_bbid: obj not found.", 0 );
      return;
    }
  }
  obj->next_bidobj = NULL;
  obj->bbid = NULL;
}

  
/* creates/destroys bounty bids, we do not use lists for this */
BBID_DATA* new_bbid(void){
  BBID_DATA* pBb = (BBID_DATA*) malloc( sizeof( *pBb ));

/* reset initial things */
  pBb->next		= NULL;
  pBb->bounty		= NULL;

  pBb->name		= str_dup("");
  pBb->level		= 0;
  pBb->pCabal		= NULL;

  pBb->cp		= 0;
  pBb->gp		= 0;

  pBb->obj		= NULL;

  return pBb;
};

void free_bbid( BBID_DATA* pBb ){
  if (pBb == NULL)
    return;

  free_string( pBb->name );
  
  pBb->next = NULL;

  free( pBb );
}

/* creates destroys bounties */
BOUNTY_DATA *bounty_free;
BOUNTY_DATA *new_bounty(){

    BOUNTY_DATA *pB;
    if (bounty_free == NULL)
	pB = alloc_perm(sizeof(*pB));
    else
    { 
      pB = bounty_free;
      bounty_free = bounty_free->next;
    }

    pB->next		= NULL;
    pB->bids		= NULL;

    pB->time_stamp	= 0;
    pB->name		= str_empty;
    
    VALIDATE(pB);
    return pB;
}

void free_bounty(BOUNTY_DATA *bounty)
{
  if (!IS_VALID(bounty))
    return;

  if (!IS_NULLSTR(bounty->name))
    free_string( bounty->name);

  /* free bids */
  while (bounty->bids){
    BBID_DATA* pBb = bounty->bids;
    bounty->bids = pBb->next;
    free_bbid( pBb );
  }

  INVALIDATE( bounty );

  bounty->next = bounty_free;
  bounty_free   = bounty;
}


/* adds a bounty onto the bounty list */
void add_bounty( BOUNTY_DATA* pb ){
  CHAR_DATA* victim;

  if (bounty_list == NULL){
    bounty_list = pb;
    pb->next = NULL;
  }
  else{
/* we always insert the bountys from oldest to newest */
    BOUNTY_DATA* last = bounty_list;
    for (last = bounty_list; last->next != NULL; last = last->next);
    pb->time_stamp = UMAX(last->time_stamp + 1, pb->time_stamp );
    last->next = pb;
    pb->next = NULL;
  }

  /* check if the target of this bounty is about */
  if ( (victim = char_file_active( pb->name)) != NULL){
    victim->pcdata->pbounty = pb;
  }
}
	

/* removes a bounty from the bounty list */
bool rem_bounty( BOUNTY_DATA* pb ){
  BOUNTY_DATA* prev = bounty_list;
  if (bounty_list == NULL){
    bug("rem_bounty: bounty_list null.", 0);
    return FALSE;
  }
  if (prev == pb )
    bounty_list = pb->next;
  else{
    while (prev->next && prev->next != pb){
      prev = prev->next;
    }
  }
  if (prev == NULL){
    bug("rem_bounty: bounty note found.", 0);
    return FALSE;
  }
  prev->next = pb->next;
  pb->next = NULL;
  return TRUE;
}

/* removes a single bid from a bounty */
void bid_from_bounty( BBID_DATA* bbid ){
  BOUNTY_DATA* bounty = bbid->bounty;

  if (bounty == NULL){
    bug("bid_from_bounty: bid not on bounty.", 0);
    return;
  }

  if (bounty->bids == bbid ){
    bounty->bids = bbid->next;
    bbid->next = NULL;
  }
  else{
    BBID_DATA* prev = bounty->bids;
    for (; prev; prev = prev->next){
      if (prev->next == bbid){
	prev->next = bbid->next;
	break;
      }
    }
    if ( prev == NULL ){
      bug( "bid_from_bounty: bid not found.", 0 );
	return;
    }
  }
  bbid->bounty = NULL;
  bbid->next = NULL;
}
  
/* adds a single bounty bid onto a bounty */
BBID_DATA* bid_to_bounty( BBID_DATA* bbid, BOUNTY_DATA* bounty ){
  if (bbid == NULL || bounty == NULL)
    return NULL;
  else if (bbid->bounty)
    bid_from_bounty( bbid );

  if (bounty->bids == NULL){
    bounty->bids = bbid;
    bbid->next = NULL;
  }
  else{
    BBID_DATA* last = bounty->bids;
    while (last->next)
      last = last->next;
    last->next = bbid;
    bbid->next = NULL;
  }
  bbid->bounty = bounty;
  return bbid;
}

/* returns bid from given bounty with given name */
BBID_DATA* get_bbid( BOUNTY_DATA* bounty, char* name ){
  BBID_DATA* bbid;
  int num = 0;
  int count = 0;

  if (bounty == NULL || IS_NULLSTR( name ))
    return NULL;
  else{
    bbid  = bounty->bids;
    num = atoi( name );
  }
  for (; bbid; bbid = bbid->next){
    if (num && ++count == num)
      return bbid;
    else if (LOWER(name[0]) == LOWER(bbid->name[0]) && !str_cmp(name, bbid->name))
      return bbid;
  }
  return NULL;
}

/* returns a bounty if found based on victim name */
BOUNTY_DATA* get_bounty( char* name ){
  BOUNTY_DATA* bounty = bounty_list;

  for (; bounty; bounty = bounty->next){
    if (LOWER(name[0]) == LOWER(bounty->name[0]) && !str_cmp(name, bounty->name))
      return bounty;
  }
  return NULL;
}

/* adds/compounds a single bid based on victim's name */
BBID_DATA* add_bounty_bid( BBID_DATA* new_bbid, char* name){
  BOUNTY_DATA* bounty;
  BBID_DATA* bbid;

  if (new_bbid == NULL || IS_NULLSTR( name ))
    return NULL;

  /* we check if there is en existing bounty */
  if ( (bounty = get_bounty( name )) == NULL){
    bounty = new_bounty();

    bounty->next	= NULL;
    
    bounty->name	= str_dup( name );
    bounty->time_stamp	= mud_data.current_time;
    bounty->bids	= new_bbid;
    add_bounty( bounty );
    return bounty->bids;
  }
  else if ( (bbid = get_bbid( bounty, new_bbid->name )) != NULL){
    OBJ_DATA* obj, *obj_next;
    /* we add the info from new bid onto existing one */
    bounty->time_stamp	= mud_data.current_time;
    bbid->level		= new_bbid->level;
    bbid->pCabal	= new_bbid->pCabal;
    bbid->cp	       += new_bbid->cp;
    bbid->gp	       += new_bbid->gp;

/* add objects */
    for (obj = new_bbid->obj; obj; obj = obj_next){
      obj_next = obj->next_bidobj;
      obj_from_bbid( obj );
      obj_to_bbid( obj, bbid );
    }
    return bbid;
  }
  else
    return bid_to_bounty( new_bbid, bounty );
  
  return NULL;
}

/* creates a linked list of ordered bounties by gold/cp/obj */
BOUNTY_DATA* make_bounty_list( BOUNTY_DATA* bounties, bool fGold, bool fObj){
  BBID_DATA* bbid;
  BOUNTY_DATA* bounty;
  BOUNTY_DATA* new_bount;

  /* run through all bounties */
  for (bounty = bounty_list; bounty; bounty = bounty->next){
    int val = 0;
    new_bount = new_bounty();
    /* get the total bid value for this bounty */
    new_bount->name = str_dup(bounty->name);
    new_bount->next = NULL;
    for (bbid = bounty->bids; bbid; bbid = bbid->next){
      if (fGold)
	val += bbid->gp;
      else if (fObj){
	OBJ_DATA* obj;
	int max_obj = 1;
	int tot_level = 0;
	for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
	  max_obj++;
	  tot_level += obj->level;
	}
	val = val + (tot_level / max_obj);
      }
      else
	val += bbid->cp;
    }
    /* at this point val has a total comparison for this bounty */
    /* we cheat and put it in new bounties time stamp */
    new_bount->time_stamp = val;
    
    /* ordered insert */
    if (bounties == NULL){
      bounties = new_bount;
      bounties->next = NULL;
    }
    else{
      BOUNTY_DATA* prev = bounties;
      BOUNTY_DATA* cur = bounties;
      while( cur ){
	if (val > cur->time_stamp)
	  break;
	else{
	  prev = cur;
	  cur = cur->next;
	}
      }
      if (prev == cur){
	new_bount->next = bounties;
	bounties = new_bount;
      }
      else{
	new_bount->next = prev->next;
	prev->next = new_bount;
      }
    }
  }
  return bounties;
}

/* show top 10 bounties */
void show_top_10( CHAR_DATA* ch ){
  const int max_10 = 10;
  char gold[max_10] [MIL];
  char cp[max_10] [MIL];
  char obj[max_10] [MIL];

  BOUNTY_DATA* bounty;
  BOUNTY_DATA* bounties = NULL;
  int count = 0;

  for (count = 0; count < max_10; count++){
    gold[count][0] = '\0';
    obj[count][0] = '\0';
    cp[count][0] = '\0';
  }
  /* we perform three similiar operations to build a linked list 
     with sorted entries according to: gold, cp, and objects
     After each build we enter the top 10 entries into the array
     destroy the list and do the next top 10
  */

  /* GOLD */
  bounties = make_bounty_list( bounties, TRUE, FALSE );
  count = 0;
  for (bounty = bounties; bounty; bounty = bounty->next){
    if (count >= max_10)
      break;
    else
      strcpy(gold[count++], bounty->name );
  }
  while (bounties){
    BOUNTY_DATA* b = bounties;
    bounties = b->next;
    free_bounty( b );
  }  
  /* CP */
  bounties = make_bounty_list( bounties, FALSE, FALSE );
  count = 0;
  for (bounty = bounties; bounty; bounty = bounty->next){
    if (count >= max_10)
      break;
    else
      strcpy(cp[count++], bounty->name );
  }
  while (bounties){
    BOUNTY_DATA* b = bounties;
    bounties = b->next;
    free_bounty( b );
  }  
  /*OBJ */
  bounties = make_bounty_list( bounties, FALSE, TRUE );
  count = 0;
  for (bounty = bounties; bounty; bounty = bounty->next){
    if (count >= max_10)
      break;
    else
      strcpy(obj[count++], bounty->name );
  }
  /* free the linked list */
  while (bounties){
    BOUNTY_DATA* b = bounties;
    bounties = b->next;
    free_bounty( b );
  }  
/* print the top out */
  send_to_char("TOP 10 BOUNTIES:\n\r", ch);
  send_to_char("Place  Gold      Cabal Pts.  Object Lvl.\n\r", ch);
  send_to_char("----------------------------------------\n\r", ch);
  for (count = 0; count < max_10; count++){
    sendf( ch, "%2d.    %-10s %-10s  %-10s\n\r",
	   count + 1,
	   gold[count] [0] ? gold[count] : "", 
	   cp[count] [0] ? cp[count] : "", 
	   obj[count] [0] ? obj[count] : "");
  }
}  
void do_top10( CHAR_DATA* ch, char* argument ){
  show_top_10( ch );
}


/* get a cost of buyout on a bounty		*
 * FORMULA for PLACE:
 140 + 60 * (10 - position)
 *
 * position = place in top10, hence:
 * - Person not in top10	: 140
 * - Person in 9th place	: 200
 * - Person in 6th place	: 380
 * - Person in 4th place	: 500
 *
 * 3rd-1st cannot be bought out.
 * position is determined as best of three categories.
 *
 * FORMULA for GOLD:
 * highest_gold_bid / 10000
 *
 * FORMULA for OBJECTS:
 * total object level * 2
 *
 * The highest worth out of Obj/Gold/Cp/Place is returned
 */

int get_buyout_cost( BOUNTY_DATA* pBounty ){
  const int max_10 = 10;
  BOUNTY_DATA* bounty;
  BOUNTY_DATA* bounties = NULL;
  BBID_DATA* bbid;
  OBJ_DATA* obj;

  int count = 0;
  int place = 99;

  int gold_cost = 0;
  int obj_cost = 0;
  int place_cost = 0;
  int cp_cost = 0;
  int cost = 0;
  


  /* get the highest place first */
  /* GOLD */
  bounties = make_bounty_list( bounties, TRUE, FALSE );
  for (bounty = bounties; bounty; bounty = bounty->next){
    if (count >= max_10)
      break;
    else if (!str_cmp(bounty->name, pBounty->name) && count < place){
      place = count;
      break;
    }
    count++;
  }
  while (bounties){
    BOUNTY_DATA* b = bounties;
    bounties = b->next;
    free_bounty( b );
  }  
  /* CP */
  bounties = make_bounty_list( bounties, FALSE, FALSE );
  count = 0;
  for (bounty = bounties; bounty; bounty = bounty->next){
    if (count >= max_10)
      break;
    else if (!str_cmp(bounty->name, pBounty->name) && count < place){
      place = count;
      break;
    }
    count++;
  }
  while (bounties){
    BOUNTY_DATA* b = bounties;
    bounties = b->next;
    free_bounty( b );
  }  
  /*OBJ */
  bounties = make_bounty_list( bounties, FALSE, TRUE );
  count = 0;
  for (bounty = bounties; bounty; bounty = bounty->next){
    if (count >= max_10)
      break;
    else if (!str_cmp(bounty->name, pBounty->name) && count < place){
      place = count;
      break;
    }
    count++;
  }
  /* free the linked list */
  while (bounties){
    BOUNTY_DATA* b = bounties;
    bounties = b->next;
    free_bounty( b );
  }  

  /* we have the lowest spot on top 10, if its 0, 1, or 2 we return negative */
  if (place < 3)
    return -1;
  else if (place == 99)
    place_cost = 140;
  else
    place_cost = 140 + 60 * (10 - place);

  /* get the other costs */
  for (bbid = pBounty->bids; bbid; bbid = bbid->next){
    int tot_level = 0;

    if (bbid->gp / 10000 > gold_cost)
      gold_cost = bbid->gp / 10000;
    if (bbid->cp > cp_cost)
      cp_cost = bbid->cp;

    for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
      tot_level += obj->level;
    }
    if (tot_level * 2 > obj_cost)
      obj_cost = tot_level * 2;
  }


  /* return highest */
  cost = place_cost;
  if (gold_cost > cost)
    cost = gold_cost;
  if (obj_cost > cost)
    cost = obj_cost;
  if (cp_cost > cost)
    cost = cp_cost;

  return cost;
}  

/* shows a bounty to a character with all its bids */
void show_bounty( CHAR_DATA* ch, BOUNTY_DATA* bounty, bool fGold, bool fObj ){
  BUFFER* buffer;
  BBID_DATA* bbid;
  BBID_DATA* bbids = NULL;

  char buf[MSL];

  long tot_gp = 0;
  long tot_cp = 0;
  int count = 0;

/* we create a temorary linked list of bounty data's by ordered inserts */
  for (bbid = bounty->bids; bbid; bbid = bbid->next){
    BBID_DATA* new_bid = new_bbid();
    int val = 0;

    new_bid->name	= str_dup( bbid->name );
    new_bid->level	= ++count;
    new_bid->pCabal	= bbid->pCabal;
    new_bid->cp		= bbid->cp;
    new_bid->gp		= bbid->gp;
    new_bid->obj	= bbid->obj; //we do not copy objects since we only need info to print later

    if (fGold)
      val = new_bid->gp;
    else if (fObj){
      OBJ_DATA* obj;
      int max_obj = 1;
      int tot_level = 0;

      for (obj = new_bid->obj; obj; obj = obj->next_bidobj ){
	max_obj++;
	tot_level += obj->level;
      }
      val = tot_level / max_obj;
    }
    else
      val = new_bid->cp;

    /* we have a value for comparison and new bbid, find insertion point */
    if (bbids == NULL){
      bbids = new_bid;
      bbids->next = NULL;
    }
    else{
      BBID_DATA* prev = bbids;
      BBID_DATA* cur = bbids;
      while( cur ){
	int key = 0;

	if (fGold)
	  key = cur->gp;
	else if (fObj){
	  OBJ_DATA* obj;
	  int max_obj = 1;
	  int tot_level = 0;
	  
	  for (obj = cur->obj; obj; obj = obj->next_bidobj ){
	    max_obj++;
	    tot_level += obj->level;
	  }
	  key = tot_level / max_obj;
	}
	else
	  key = cur->cp;
	
	/* we now have a key and value to compare */
	if (val > key)
	  break;
	else{
	  prev = cur;
	  cur = cur->next;
	}
      }
      if (prev == cur){
	new_bid->next = bbids;
	bbids = new_bid;
      }
      else{
	new_bid->next = prev->next;
	prev->next = new_bid;
      }
    }
  }

  /* at this point we have a linked list bbids full of sorted bids, we show them. */
  buffer = new_buf();
  sprintf( buf, "Bids set for %s's head listed in order of %s.\n\r",
	   bounty->name,
	   fObj ? "AVERAGE OBJECT RANK" : fGold ? "GOLD AMOUNT" : "CABAL POINTS");
  add_buf( buffer, buf );
  for (bbid = bbids; bbid; bbid = bbid->next){
    OBJ_DATA* obj;
    tot_cp += bbid->cp;
    tot_gp += bbid->gp;
    sprintf( buf, "%2d: Gp: %-10ld Cp: %-10d\n\r", bbid->level, bbid->gp, bbid->cp);
    add_buf( buffer, buf );
    if (bbid->obj){
      add_buf(buffer, "    ");
      for (obj = bbid->obj; obj; obj = obj->next_bidobj){
	sprintf(buf, "%-12.12s, ", obj->short_descr);
	add_buf( buffer, buf );
      }
      add_buf( buffer, "\n\r");
    }
  }
  sprintf(buf, "This bounty will expire in %ld days.\n\r",
	  (BOUNTY_LIFETIME - mud_data.current_time + bounty->time_stamp) / 86400);
  add_buf( buffer, buf );
  page_to_char(buf_string(buffer),ch);
  free_buf(buffer);

  /* free the linked list */
  while (bbids){
    bbid = bbids;
    bbids = bbid->next;
    bbid->obj = NULL; //we do not free objets since we only linked to them
    free_bbid( bbid );
  }
}
      
    
	

      

  
void show_bbid( CHAR_DATA* ch, BBID_DATA* bbid ){
  OBJ_DATA* obj;
  char buf[MSL];

  if (ch == NULL || bbid == NULL)
    return;

  sendf(ch, 
	 "Gold  : %-10ld %s%s: %-10d\n\r",
	bbid->gp,
	ch->pCabal ? capitalize(ch->pCabal->currency) : "CP",
	ch->pCabal ? bbid->cp == 1 ? "" : "s" : "",
	bbid->cp);
  if (bbid->obj == NULL){
    return;
  }
  else{
    int count = 0;
    sprintf(buf, "Objects:\n\r");
    for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
      sprintf( buf + strlen( buf ), "%d. %s\n\r",
	       ++count,
	       obj->short_descr);
    }
    send_to_char( buf, ch );
    send_to_char("\n\r", ch );
  }
}
  
    
  
/* MAIN BOUNTY FUNCTION TO CREATE BOUNTY BIDS */
/* Syntax:

   bounty cp <amount>	: set amount of cabal points on your bid
   bounty gold <amount>	: set amount of gold on your bid
   bounty add <object>	: add object to the bid
   bounty rem <object>	: remove object from the bid
   bounty place <name>	: place current bounty bid onto character <name>

   bounty <name>	: show your bids on character <name>
   bounty		: show current bid
*/
void do_bounty( CHAR_DATA* ch, char* argument ){
  char arg[MIL];
  int val;

  if (IS_NPC(ch))
    return;
  else
    argument = one_argument( argument, arg );
  
  if (IS_NULLSTR( arg )){
    if (ch->pcdata->pbbid){
      send_to_char("Your current bounty bid is composed of:\n\r", ch );
      show_bbid(ch, ch->pcdata->pbbid);
    }
    send_to_char("Bounty <cp/gold/add/rem/place/buyout> (\"help bounty\" for details).\n\r", ch );
    return;
  }
  else if (!str_prefix( arg, "cp")){
    if (ch->pCabal == NULL){
      send_to_char("You are not in a cabal!\n\r", ch );
      return;
    }
    if (ch->pcdata->pbbid == NULL)
      ch->pcdata->pbbid = new_bbid();

    if ( (val = atoi( argument )) < 30){
      sendf(ch, "You must place at last 30 %ss.\n\r", ch->pCabal->currency );
      return;
    }
    else if (val > GET_CP(ch)){
      int dif = val - GET_CP( ch );
      sendf( ch, "You are short %d %s%s.\n\r", dif, ch->pCabal->currency, dif == 1 ? "" : "s" );
      return;
    }
    else{
      ch->pcdata->pbbid->cp = val;
      sendf( ch, "Your bounty now includes %d %s%s.\n\r", ch->pcdata->pbbid->cp, 
	     ch->pCabal->currency, 
	     ch->pcdata->pbbid->cp == 1 ? "" : "s" );
    }
    return;
  }
  else if (!str_prefix( arg, "gold")){
    if (ch->pcdata->pbbid == NULL)
      ch->pcdata->pbbid = new_bbid();

    /* get minimum bid for this character */
    if ( (val = atoi( argument )) < 10000){
      send_to_char("You must place at least 10k gold.\n\r", ch );
      return;
    }
    else if (val > ch->in_bank){
      int dif = val - ch->in_bank;
      sendf( ch, "You are short %d gold in your bank account.", dif);
      return;
    }
    else{
      ch->pcdata->pbbid->gp = val;
      sendf( ch, "Your bounty now includes %ld gold.\n\r", ch->pcdata->pbbid->gp );
    }
    return;
  }
  else if (!str_prefix( arg, "add")){
    OBJ_DATA* obj, *pObj;
    int count = 0;


    if (IS_NULLSTR( argument )){
      send_to_char("Add what object to the bounty?\n\r", ch );
      return;
    }
    else if ( (obj = get_obj_carry( ch, argument, ch )) == NULL){
      send_to_char("You do not seem to be carrying that object.\n\r", ch );
      return;
    }
    else if (!IS_LIMITED( obj )){
      send_to_char("That object is too common to be placed as a bounty.\n\r", ch );
      return;
    }
    else if (obj->bbid != NULL){
      send_to_char("That object already seems to be part of your bounty.\n\r", ch );
      return;
    }
    else if (!can_drop_obj(ch, obj )){
      send_to_char("You must be able to part with the item first.\n\r", ch );
      return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_CLONE){
      send_to_char("Placing a counterfit item as a bounty is a sure way to die.\n\r", ch);
      return;
    }
    else if (obj->contains && !IS_OBJ_STAT(obj, ITEM_SOCKETABLE)) {
      send_to_char("You may not place objects that are containers, or loaded.\n\r", ch );
      return;
    }

    if (ch->pcdata->pbbid == NULL)
      ch->pcdata->pbbid = new_bbid();

    /* count how many objects on this bid */
    for (pObj = ch->pcdata->pbbid->obj; pObj; pObj = pObj->next_bidobj )
      count++;
    if (count + 1 > 5){
      send_to_char("You may place a maximum of five objects as a bounty.\n\r", ch );
      return;
    }

    /* we attach the object into this bid data BUT DO NOT remove it from character, "place" command will do all that */
    if (ch->pcdata->pbbid->obj == NULL){
      obj->next_bidobj = NULL;
      ch->pcdata->pbbid->obj = obj;
    }
    else{
      obj->next_bidobj = ch->pcdata->pbbid->obj;
      ch->pcdata->pbbid->obj = obj;
    }
    obj->bbid = ch->pcdata->pbbid;
    sendf( ch, "You have added %s to the bounty.\n\r", obj->short_descr);

    /* we store the count in bbid->level to be used in "place" command */
    ch->pcdata->pbbid->level = count + 1;
    return;
  }
  else if (!str_prefix( arg, "rem")){
    OBJ_DATA* obj;

    if (ch->pcdata->pbbid == NULL || ch->pcdata->pbbid->obj == NULL){
      send_to_char("You have not placed any objects as a bounty.\n\r", ch);
      return;
    }
    else if (IS_NULLSTR( argument )){
      send_to_char("Remove what object from the bounty?\n\r", ch );
      return;
    }
    else if ( (obj = get_obj_carry( ch, argument, ch )) == NULL){
      send_to_char("You do not seem to be carrying that object.\n\r", ch );
      return;
    }
    else if (obj->bbid == NULL){
      send_to_char("That object is has not been placed as a bounty.\n\r", ch );
      return;
    }
    else if (obj->bbid != ch->pcdata->pbbid){
      send_to_char("That object has not been placed into the bounty you are working on.\n\r", ch );
      return;
    }
    
    obj_from_bbid( obj );
    ch->pcdata->pbbid->level --;

    sendf( ch, "You have removed %s from the bounty.\n\r", obj->short_descr);
    return;
  }
  /* none of the commands matched, try to place the bounty */
  else if (!str_prefix( arg, "place")){
    CHAR_DATA* victim;
    CHAR_DATA* mob;
    DESCRIPTOR_DATA* d;
    BBID_DATA* bbid, *oldBbid;
    BOUNTY_DATA* oldBounty;

    int coffers = 0, cost = 0;
    bool fPurge = FALSE;

    long min_gp = 0, min_cp = 0;

    for (mob = ch->in_room->people; mob; mob = mob->next_in_room ){
      if (IS_NPC(mob) && IS_SET(mob->act, ACT_CONTRACTER))
	break;
    }
    if (mob == NULL){
      send_to_char("There is no one here to record your bounty.\n\r", ch);
      return;
    }
    else if (ch->pcdata->pbbid == NULL){
      do_bounty( ch, "" );
      return;
    }
    else if (IS_NULLSTR( argument)){
      send_to_char("Place this bounty on who?\n\r", ch );
      return;
    }
    else
      bbid = ch->pcdata->pbbid;

    /* try to get the victim of this bounty */
    if ( (victim = char_file_active (argument)) == NULL){
      if ( (d = bring( ch->in_room, argument )) != NULL){
	victim = d->character;
	fPurge = TRUE;
	victim->pcdata->roomnum *= -1;
      }
      else{
	send_to_char ("That character does not exist.\n\r", ch);
	return;
      }
    }

    /* we now have the victm of this bounty, do some checks */
    if (IS_NPC(victim)){
      send_to_char("Why would you want to place a bounty on a mobile?\n\r", ch );
      return;
    }
    else if (mud_data.current_time < victim->pcdata->last_bounty + BOUNTY_WAITTIME){
      send_to_char("Their bounty has been recently claimed. Try again later.\n\r", ch);
      if (fPurge)
	purge( victim );
      return;
    }

    /* calculate minimums */
    min_gp = 100 * victim->level + (victim->pcdata->kpc / UMAX(1, victim->pcdata->dpc)) * 10000;
    min_cp = UMAX(30, min_gp / 1000);

    /* find old bid if any */
    if ( (oldBounty = get_bounty( victim->name )) != NULL
       && (oldBbid = get_bbid( oldBounty, ch->name )) != NULL){
      min_gp -= oldBbid->gp;
      min_cp -= oldBbid->cp;
    }
    min_gp = UMAX(5000, min_gp );
    min_cp = UMAX(30, min_cp );

    if (victim->level < 15)
      send_to_char("You may not place bounties on victims of rank lower then 15th.\n\r", ch );
    else if (ch == victim)
      send_to_char("You cannot place bounties on yourself.\n\r", ch );
    else if (mud_data.mudport != TEST_PORT && ch->pCabal && IS_CABAL(ch->pCabal, CABAL_ROUGE))
      send_to_char("Your job is to collect the bounties, not place them.\n\r", ch );
    else if (victim->pCabal && IS_CABAL(victim->pCabal, CABAL_ROUGE))
      act("$N seems to ignore your request.", ch, NULL, mob, TO_CHAR);
    else if (mud_data.mudport != TEST_PORT && (IS_IMMORTAL( ch ) || IS_IMMORTAL(victim)) )
      send_to_char("Gods are above such petty behavior.  Event logged.\n\r", ch );
    else if (bbid->obj && victim->level < 40 && victim->pCabal == NULL)
      send_to_char("In order to place equipment as a bounty your victim must be of rank 40+ or cabaled.\n\r", ch );
    /* minimum gold */
    else if (bbid->gp && bbid->gp < min_gp){
      sendf(ch, "The minimum gold bid on %s is %ld gold.\n\r", victim->name, min_gp);
    }
    else if (ch->pCabal && bbid->cp && bbid->cp < min_cp){
      sendf(ch, "The minimum %s bid on %s is %ld %ss.\n\r", 
	    ch->pCabal->currency, 
	    victim->name, 
	    min_cp,
	    ch->pCabal->currency);
    }
    else if (ch->in_bank < bbid->gp)
      send_to_char("You do not have enough gold in the bank.\n\r", ch );
    else if (ch->pCabal && GET_CP( ch ) < bbid->cp )
      sendf( ch, "You do not have enough %s%s.", ch->pCabal->currency, bbid->cp == 1 ? "" : "s" );
    else if (bbid->obj == NULL && bbid->cp == 0 && bbid->gp == 0)
      send_to_char("Your bid does has no value.\n\r", ch );
    else{
      /* we can now create a real bid, and transfer stuff over */
      BBID_DATA* new_bid;
      BOUNTY_DATA* bounty = NULL;
      OBJ_DATA* obj, *obj_next;

      /* check if we can add objects into this bid */
      if (bbid->obj
	  && (bounty = get_bounty( victim->name)) != NULL
	  && (new_bid = get_bbid( bounty, ch->name)) != NULL){
	int count = 0;
	for (obj = new_bid->obj; obj; obj = obj->next_bidobj )
	  count ++;

	if (count + bbid->level > 5){
	  if (5 - count >= 0)
	    sendf(ch, "You have previously placed %d items as a bounty and may place only %d more.\n\r", count, 5 - count);
	  else
	    send_to_char("You may only place up to 5 items as a bounty.\n\r", ch );
	  if (fPurge)
	    purge( victim );
	  return;
	}
      }

      new_bid = new_bbid();
      new_bid->name	= str_dup( ch->name );
      new_bid->level	= ch->level;
      new_bid->pCabal	= ch->pCabal;
      new_bid->cp	= ch->pCabal ? bbid->cp : 0;
      new_bid->gp	= bbid->gp;

      /* subtract gold, cp's */
      /* check if cabal can cover half */
      cost = bbid->cp;
      if (ch->pCabal && IS_CABAL(get_parent(ch->pCabal), CABAL_ROYAL)){
	CABAL_DATA* pCab = get_parent(ch->pCabal);
	if (GET_CAB_CP(pCab) - 500 > bbid->cp / 2){
	  coffers = bbid->cp / 2;
	  cost = bbid->cp / 2;
	}

	if (coffers){
	  char buf[MIL];
	  sprintf( buf, "%s has been given %d %s%s from our coffers.",
		   PERS2( ch ),
		   coffers,
		   pCab->currency,
		   coffers == 1 ? "" : "s");
	  cabal_echo( pCab, buf );
	  CP_CAB_GAIN( pCab, -coffers );
	}
      }
	
      CP_GAIN( ch, -cost, TRUE );
      ch->in_bank -= new_bid->gp;

      for (obj = bbid->obj; obj; obj = obj_next){
	obj_next = obj->next_bidobj;
	obj_from_bbid( obj );
	obj_from_char( obj );
	obj_to_bbid( obj, new_bid );
      }

      /* the new_bid now contains all the info, we get rid of the old one */
      free_bbid( ch->pcdata->pbbid );
      ch->pcdata->pbbid = NULL;

      /* we now add the bid for the victim */
      if ( (new_bid = add_bounty_bid( new_bid, victim->name )) == NULL){
	send_to_char("There was a problem setting your bounty.\n\r", ch );
	return;
      }
      else
	save_bounties();
      /* send a message to the victim */
      if (victim->pCabal && IS_CABAL(get_parent(victim->pCabal), CABAL_SPIES) ){
	if (!fPurge)
	  sendf( victim, "[%s] contacts in the underworld report %s's bounty on your head.\n\r",
		 victim->pCabal->who_name, ch->name);
	else{
	  char buf[MIL];
	  SET_BIT(victim->pcdata->messages, MSG_BOUNTY );
	  sprintf( buf, "[%s] contacts in the underworld report %s's bounty on your head.\n\r",
		   victim->pCabal->who_name, ch->name);
	  do_hal(victim->name, "A bounty has been set upon your head.", buf, NOTE_NOTE);
	}
      }
      sendf( ch, "Your current bounty for %s:\n\r", PERS2( victim ));
      show_bbid( ch, new_bid );
      send_to_char( "\n\r", ch );
      if (mob){
	act("$N nods ever so slightly and turns $S back on you.", ch, NULL, mob, TO_CHAR);
	act("$N nods ever so slightly and turns $S back on $n.", ch, NULL, mob, TO_ROOM);
      }
    }
    if (fPurge )
      purge( victim );
  }
  else if (!str_prefix( arg, "clear")){
    if (ch->pcdata->pbbid == NULL){
      send_to_char("You are not working on a bounty.\n\r", ch );
      return;
    }
    else{
      OBJ_DATA* obj, *obj_next;

      for (obj = ch->pcdata->pbbid->obj; obj; obj = obj_next){
	obj_next = obj->next_bidobj;
	obj_from_bbid( obj );
      }
      free_bbid( ch->pcdata->pbbid);
      ch->pcdata->pbbid = NULL;
      send_to_char("Bounty data cleared.\n\r", ch );
    }
    return;
  }
/* BUYOUT */
  else if (!str_prefix( arg, "buyout")){
    BOUNTY_DATA* bounty;
    CABAL_DATA* pCab = get_parent(ch->pCabal);
    CABAL_DATA* pRouge = NULL;
    PACT_DATA* pp;
    int cost = 0, coffers = 0;
    char buf[MIL];


    if (pCab == NULL){
      send_to_char("You must be a member of a cabal.\n\r", ch);
      return;
    }
    else if (!IS_CABAL(pCab, CABAL_ALLIANCE)){
      send_to_char("You lack the contacts neccessary.\n\r", ch);
      return;
    }
    /* check for an alliance with a rouge cabal */
    for (pp = pact_list; pp; pp = pp->next){
      if (pp->complete != PACT_COMPLETE)
	continue;
      if ( pp->type != PACT_ALLIANCE )
	continue;
      if (pp->benefactor == pCab &&  IS_CABAL(pp->creator, CABAL_ROUGE)){
	pRouge = pp->creator;
	break;
      }
      else if(IS_CABAL(pp->benefactor, CABAL_ROUGE) && pp->creator == pCab){
	pRouge = pp->benefactor;
	break;
      }
    }
    
    if (pRouge == NULL){
      send_to_char("You lack the contacts neccessary.\n\r", ch);
      return;
    }
    else if ( (bounty = ch->pcdata->pbounty) ==  NULL){
      send_to_char("There are no bounties associated with you.\n\r", ch );
      return;
    }
    
    /* get the cost */
    cost = get_buyout_cost( bounty );

    if (cost < 1){
      send_to_char("You may not buy out your bounty.\n\r", ch);
      return;
    }

    if (IS_CABAL(pCab, CABAL_ROYAL) && GET_CAB_CP(pCab) - 500 > cost / 2){
      cost = cost / 2;
      coffers = cost;
    }

    if (IS_NULLSTR(argument)){
      if (coffers){
	sendf(ch, "The bribe will cost you %d %s%s with %d being covered by [%s] coffers.\n\r", 
	      cost, 
	      pCab->currency,
	      cost == 1 ? "" : "s",
	      coffers,
	      pCab->who_name);
      }
      else{
	sendf(ch, "The bribe will cost %d %s%s.\n\r",
	      cost, 
	      pCab->currency,
	      cost == 1 ? "" : "s");
      }
      send_to_char("Use \"bounty buyout confirm\" to end the transaction.\n\r", ch);
    }
    else{
      if (GET_CP( ch ) < cost){
	send_to_char("You lack the funds neccessary.\n\r", ch);
	return;
      }
      else if (coffers && GET_CAB_CP(pCab) < coffers){
	send_to_char("Your cabal lacks the funds neccessary.\n\r", ch);
	return;
      }

      /* remove the bounty */
      rem_bounty( ch->pcdata->pbounty );
      free_bounty( ch->pcdata->pbounty );
      save_bounties();
      ch->pcdata->pbounty = NULL;
      /* mark time for re-biounty wait */
      ch->pcdata->last_bounty = mud_data.current_time;

      sprintf( buf, "%s has graciously donated %d %ss to our cause.",
	       PERS2( ch ),
	       cost + coffers,
	       pCab->currency);
      cabal_echo( pRouge, buf );

      if (coffers){
	sprintf( buf, "%s has been given %d %s%s from our coffers.",
		 PERS2( ch ),
		 coffers,
		 pCab->currency,
		 coffers == 1 ? "" : "s");
	cabal_echo( pCab, buf );
	CP_CAB_GAIN( pCab, -coffers );
      }
      CP_GAIN( ch, -cost, TRUE );
      CP_CAB_GAIN(pRouge, coffers + cost );
      save_char_obj( ch );
    }
    return;
  }
  /* check if we have any bounties on this person */
  else if (!IS_NULLSTR( arg )){
    BOUNTY_DATA* bounty = get_bounty( arg );
    BBID_DATA* bbid;

    if (bounty == NULL || (bbid = get_bbid( bounty, ch->name )) == NULL){
      sendf( ch, "You have not placed any bounties for their death.\n\r");
      return;
    }
    else{
      sendf( ch, "Your current bounty for %s:\n\r", bounty->name );
      show_bbid( ch, bbid );
      sendf(ch, "This bounty will expire in %ld days.\n\r",
	    (BOUNTY_LIFETIME - mud_data.current_time + bounty->time_stamp) / 86400);


    }
    return;
  }
  else
    do_bounty( ch, "" );
}


/* returns a single bid from a bounty to its owner */
void return_bbid( BBID_DATA* bbid, char* name ){
  CHAR_DATA* owner;
  DESCRIPTOR_DATA* d;
  ROOM_INDEX_DATA* to_room;
  OBJ_DATA* obj, *obj_next;

  bool fPurge = FALSE;
  int count = 0;
  
  if (bbid == NULL || IS_NULLSTR(name))
    return;

  /* get transfer room first */
  if ( (to_room = get_room_index(ROOM_VNUM_LIMBO)) == NULL){
    bug("return_bbid: could not get limbo room.", 0);
    return;
  }
  else if ( (owner = char_file_active (name)) == NULL){
    if ( (d = bring( to_room, name )) != NULL){
      owner = d->character;
      fPurge = TRUE;
      owner->pcdata->roomnum *= -1;
    }
    else{
      owner = NULL;
    }
  }
  /* at this point we stop if pfile no longer exists */
  if (owner == NULL){
    return;
  }

  /* transfer items from bid */
  for (obj = bbid->obj; obj; obj = obj_next){
    obj_next = obj->next_bidobj;
    
    obj_from_bbid( obj );

    if (!can_take(owner, obj)){
      extract_obj( obj );
      continue;
    }
    else{
      obj_to_char( obj, owner );
      count++;
    }
  }

  /* return gold */
  owner->in_bank += bbid->gp;
  CP_GAIN(owner, bbid->cp, TRUE );
  
  if (fPurge && count)
    SET_BIT(owner->pcdata->messages, MSG_BOUNTY_RETURN);
  else if (count){
    sendf( owner, "`@Your bounty on %s has been returned.``\n\r",
	   bbid->bounty->name);
  }
  if (fPurge)
    purge( owner );
}
/* returns an entire bounty to their owners */
void return_bounty( BOUNTY_DATA* bounty, BBID_DATA* exempt ){
  BBID_DATA* bbid, *bbid_next;

  for (bbid = bounty->bids; bbid; bbid = bbid_next){
    bbid_next = bbid->next;

    if (exempt && bbid == exempt)
      continue;
    return_bbid(bbid, bbid->name );
  }
}

/* writes a single bounty bid to a file */
void fwrite_bbid( FILE* fp, BBID_DATA* bbid ){
  OBJ_DATA* obj;

  fprintf( fp, "#BBID %s~ %d %d %d %ld\n",
	  bbid->name,
	  bbid->pCabal ? bbid->pCabal->vnum : 0,
	  bbid->level,
	  bbid->cp,
	  bbid->gp );

  /* write objects if any */
  for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
    fwrite_obj(NULL, obj, fp, 0, 0, FALSE);
  }
/* terminate */
  fprintf( fp, "#End\n" );
}

/* reads a single bounty bid from file */
void fread_bbid( FILE* fp, BBID_DATA* bbid ){
  ROOM_INDEX_DATA* bounty_room;
  OBJ_DATA* obj;

  char letter;
  char* word;

  bbid->name		= fread_string( fp );
  bbid->pCabal		= get_cabal_vnum( fread_number( fp ) );
  bbid->level		= fread_number( fp );
  bbid->cp		= fread_number( fp );
  bbid->gp		= fread_number( fp );

  /* make sure we can get the bounty room */
  if ( (bounty_room = get_room_index( ROOM_VNUM_BOUNTY)) == NULL){
    bug("fread_bbid: could not get bounty room.", 0);
    exit( 1 );
  }

/* start the loop to read objects */
  for (;;){
    letter		= fread_letter( fp );
    if ( letter != '#' ){
      bug( "read_bbid: # not found.", 0 );
      exit( 1 );
    }
    word   = feof( fp ) ? "End" : fread_word( fp );
    if ( !str_cmp(word, "End"))
      break;
    else if (!str_cmp(word, "O") || !str_cmp(word, "OBJECT")){
      if ( (obj = fread_obj( NULL, fp, bounty_room )) == NULL){
	bug("fread_bbid: could not load object.", 0);
      }
      else{
	obj_to_bbid( obj, bbid );
      }
      continue;
    }
  }
}

/* writes a single bounty */
void fwrite_bounty( FILE* fp, BOUNTY_DATA* bounty ){
  BBID_DATA* bbid;
  struct stat Stat;	//File statistics
  char pFile [MIL];

  /* check if this player file exists */
  /* Get info/pointer to file entry*/
  sprintf(pFile, PLAYER_DIR"%s", bounty->name);
  if ( -1 == stat( pFile, &Stat))
    return;
  
  fprintf( fp, "#BOUNTY %s~ %ld\n", bounty->name, bounty->time_stamp );

  /* save bids */
  for (bbid = bounty->bids; bbid; bbid = bbid->next ){
    fwrite_bbid( fp, bbid );
  }
  
  /* terminate */
  fprintf( fp, "#End\n" );

}

/* reads a single bounty */
void fread_bounty( FILE* fp, BOUNTY_DATA* bounty ){
  char letter;
  char* word;

  bounty->name		= fread_string( fp );
  bounty->time_stamp	= fread_number( fp );

  /* read in the individual bids */
  for (;;){
    letter		= fread_letter( fp );
    if ( letter != '#' ){
      bug( "read_bounty: # not found.", 0 );
      exit( 1 );
    }
    word   = feof( fp ) ? "End" : fread_word( fp );
    if ( !str_cmp(word, "End"))
      break;
    else if (!str_cmp(word, "BBID")){
      BBID_DATA* bbid = new_bbid();
      fread_bbid( fp, bbid );
      bid_to_bounty( bbid, bounty );
    }
  }
}


/* saves all the bounties */
void save_bounties( ){
  FILE *fp;
  BOUNTY_DATA* bounty = bounty_list;
  char path[128];

  fclose( fpReserve );
  sprintf( path, "%s%s", SAVEBOUNTY_DIR, SAVEBOUNTY_FILE);
  if ( ( fp = fopen( path, "w" ) ) == NULL ){
    fp = fopen( NULL_FILE, "r" );
    fclose (fp);
    perror( path );
    return;
  }
/* loop through bounties and save */
  for (; bounty; bounty = bounty->next ){
    fwrite_bounty( fp, bounty );
  }
  fprintf( fp, "#END\n" );
  fclose( fp );
  fpReserve = fopen( NULL_FILE, "r" );
}

/* checks bounties after loading in order to free the timed out ones */
void fix_bounties(){
  BOUNTY_DATA* bounty = bounty_list, *bounty_next;

/* loop through bounties and check */
  for (; bounty; bounty = bounty_next ){
    bounty_next = bounty->next;
    /* check if this bounty should be released */
    if (mud_data.current_time -  bounty->time_stamp > BOUNTY_LIFETIME){
      return_bounty( bounty, NULL );
      rem_bounty( bounty );
      free_bounty( bounty );
    }
  }
  save_bounties();
}

/* reads all bounties */
void load_bounties(){
  BOUNTY_DATA* bounty;
  FILE *fp;
  char path[128];
  char letter;
  char* word;

  fclose( fpReserve );
  sprintf( path, "%s%s", SAVEBOUNTY_DIR, SAVEBOUNTY_FILE);
  if ( ( fp = fopen( path, "r" ) ) == NULL ){
    fp = fopen( NULL_FILE, "r" );
    fclose (fp);
    perror( path );
    return;
  }
  
  for (;;){
    letter		= fread_letter( fp );
    if ( letter != '#' ){
      bug( "load_bounties: # not found.", 0 );
      exit( 1 );
    }
    word   = feof( fp ) ? "END" : fread_word( fp );
    if ( !str_cmp(word, "END"))
      break;
    else if (!str_cmp(word, "BOUNTY")){
      bounty = new_bounty();
      fread_bounty( fp, bounty );
      add_bounty( bounty );
    }
  }
  fclose( fp );
  fpReserve = fopen( NULL_FILE, "r" );

  fix_bounties();
}



/* handles all the misc. tasks after a bountied victim is killed */
void fulfill_bounty( CHAR_DATA *ch, CHAR_DATA *victim, char* name){
  CHAR_DATA* bidder;
  DESCRIPTOR_DATA* d;
  OBJ_DATA* obj, *obj_next;
  BBID_DATA* bbid;
  CABAL_DATA* pAlly = NULL;
  AFFECT_DATA* paf;

  const int cab_share = 75;	//percent taken by cabal,  if not allied kill
  
  long gold	= 0;
  int	cp	= 0;
  int cp_cab	= 0;
  int count	= 0;
  int corp_count= 0;

  bool fPurge = FALSE;

  char buf[MSL];
  char to[MSL];


/* safety */
  if (IS_NPC(ch) || IS_NPC(victim))
    return;
  else if (victim->pcdata->pbounty == NULL){
    bug("fulfill_bounty: victim with no bounty.\n\r", 0 );
    return;
  }
/* try to get the bid by name */
  if ( (bbid = get_bbid( victim->pcdata->pbounty, name)) == NULL){
    if ( (bbid = victim->pcdata->pbounty->bids) == NULL){
      bug("fulfill_bounty: bounty with no bids.", 0);
      return;
    }
  }
   
  /* set transfer for cp/gp, if this is not an allied kill, then cabal takes cab_share% to coffers */
  gold = pAlly ? bbid->gp : cab_share * bbid->gp / 100;
  cp_cab = pAlly ? 0 : cab_share * bbid->cp / 100;
  cp = bbid->cp - cp_cab;

  /* transfer bounty items to killer */
  for (obj = bbid->obj; obj; obj = obj_next){
    obj_next = obj->next_bidobj;
    
    obj_from_bbid( obj );

    if (!can_take(ch, obj)){
      sendf( ch, "You could not use %s.\n\rIt has been sold to help widowed families of %s%s%s.\n\r",
	     obj->short_descr, 
	     ch->pCabal ? "[" : "",
	     ch->pCabal ? ch->pCabal->who_name : victim->name,
	     ch->pCabal ? "]" : "");
      extract_obj( obj );
      continue;
    }
    else{
      obj_to_char( obj, ch );
      count++;
    }
  }
  if (ch->pCabal){
    /* do cp event bounty to reward */
    cp_event( ch, victim, NULL, CP_EVENT_BOUNTY);

    if (cp_cab > 0){
      sprintf( buf, "%d %s%s %s been directed to our coffers from %s's bounty.",
	       cp_cab, 
	       ch->pCabal->currency,
	       cp_cab == 1 ? "" : "s",
	       cp_cab == 1 ? "has" : "have",
	       PERS2(victim));
      cabal_echo( get_parent( ch->pCabal ), buf);
      CP_CAB_GAIN( ch->pCabal, cp_cab );
    }
    if (cp)
      CP_GAIN( ch, cp, TRUE );
  }
  /* transfer best three rares to the killer */
  corp_count = get_random_rares( ch, victim, 3, FALSE );

  /* if the bountier exists and is of rank > 40 he gets the rest of rares up to 18 */
  if ( (bidder = char_file_active (bbid->name)) == NULL){
    if ( (d = bring( ch->in_room, bbid->name )) != NULL){
      bidder = d->character;
      fPurge = TRUE;
      bidder->pcdata->roomnum *= -1;
    }
    else{
      bidder = NULL;
    }
  }
  if (bidder && bidder->level >= 40){
    int bidder_count = get_random_rares(bidder, victim, 18, FALSE );
    if (fPurge && bidder_count)
      SET_BIT(bidder->pcdata->messages, MSG_BOUNTY_REWARD);
    else if (bidder_count)
      sendf( ch, "`@You have recived %d items as a result of %s's death to a bounty hunter.``\n\r",
	     bidder_count, victim->name);
  }
  if (fPurge && bidder)
    purge( bidder );
  ch->in_bank += gold;
  if (gold || count || corp_count)
    sendf( ch, "You've recived %ld gold, %d items from the bounty and %d items from the corpse.\n\r",
	   gold, count, corp_count );

  /* we create a single note to all the people that bid on this bounty */
  to[0] = '\0';
  for (bbid = victim->pcdata->pbounty->bids; bbid; bbid = bbid->next){
    strcat(to, bbid->name);
    strcat(to, " ");
  }
  sprintf( buf, warn_table[WARN_BOUNTY].subj, victim->name );
  
  do_hal( to, buf, warn_table[WARN_BOUNTY].text, NOTE_NOTE);

  /* get rid of contract */
  if ( (paf = affect_find( ch->affected, gen_contract)) != NULL){
    paf->modifier = TRUE;
    affect_remove( ch, paf );
  }
  /* return rest of the bids */
  return_bounty( victim->pcdata->pbounty, bbid);

  /* we clear the bounty for the victim */
  rem_bounty( victim->pcdata->pbounty );
  free_bounty( victim->pcdata->pbounty );
  save_bounties();
  victim->pcdata->pbounty = NULL;
  /* mark time for re-biounty wait */
  victim->pcdata->last_bounty = mud_data.current_time;

  /* increae the count of bounties collected */
  mud_data.bounties++;
/* if this is a cabaled killer from bounty cabal, increase bounty count */
  if (ch->pCabal && IS_CABAL(ch->pCabal, CABAL_ROUGE))
    ch->pcdata->member->kills++;
  save_mud();
}

/* handles selection and collection of bounty */
/* SYNTAX:
   collect <name>		: collects first avaliable bounty
   collect <name> <number>	: collects the selected bounty
   collect list <name>		: list all bids by cp
   collect gold <name>		: list by gold
   collect obj <name>		: list by obj
   collect list <name> <number>	: list the bid in detail

*/
void do_bounty_collect( CHAR_DATA *ch, char *argument ){

  AFFECT_DATA* paf = NULL;
  CHAR_DATA *victim;
  OBJ_DATA *obj;
  
  char arg[MIL];
  char buf[MSL];
  
  argument = one_argument( argument, arg);
  
  if ((ch->pCabal == NULL || !IS_CABAL(ch->pCabal, CABAL_ROUGE))
      && ( (paf = affect_find(ch->affected, gen_contract)) == NULL
	   || !paf->has_string
	   || IS_NULLSTR(paf->string)) ){
    send_to_char("Huh?\n\r", ch );
    return;
  }
  else if (IS_NULLSTR( arg )){
    send_to_char("Seek scrolls of \"help collect\" for details.\n\r", ch );
    return;
  }
/* LIST */
  else if (!str_cmp( "list", arg) || !str_cmp( "gold", arg) || !str_cmp( "obj", arg)){
      BOUNTY_DATA* bounty;
      BBID_DATA* bbid;
      char arg2[MIL];
      argument = one_argument( argument, arg2);
  
      if (paf)
	strcpy(arg2, paf->string);
	  
      if (IS_NULLSTR( arg2 )){
	send_to_char("List the bounty for who?\n\r", ch );
	return;
      }
      else if ( (bounty = get_bounty( arg2)) == NULL){
	send_to_char("There is no price on their head.\n\r", ch);
	return;
      }
      /* VIEW */
      if (!IS_NULLSTR( argument )){
	if (atoi( argument ) < 1){
	  send_to_char("View which bounty? (number)\n\r", ch );
	  return;
	}
	else if ( (bbid = get_bbid( bounty, argument)) == NULL){
	  sendf(ch, "No such bounty foundf or %s.\n\r", bounty->name );
	  return;
	}
	else{
	  sendf(ch, "Victim: %-15s  Bounty: %d\n\r", bounty->name, atoi(argument) );
	  show_bbid( ch, bbid );
	}
	return;
      }
      else
	show_bounty( ch, bounty, !str_cmp(arg, "gold"), !str_cmp(arg, "obj") );
      return;
    }
    else if ( (victim = get_char_room( ch, NULL, arg ) ) == NULL ){
      send_to_char( "They aren't here.\n\r", ch );
      return;
    }
  else if (!can_collect(victim->pcdata->pbounty, ch)){
    sendf(ch, "You cannot collect bounty on %s\n\r.", PERS2(victim) );
    return;
  }
  else if (IS_NPC(ch) || IS_NPC(victim)){
    send_to_char("Not on mobiles.\n\r", ch );
    return;
  }
  else if (!is_pk_abs(ch, victim)){
    send_to_char("The gods will not allow you to harm them.\n\r", ch);
    return;
  }
  else if ( !is_affected(victim, gsn_mortally_wounded) ){
    sendf(ch, "%s is not standing still enough for you to collect a bounty.\n\r", PERS2(victim));
    return;
  }
  
  sprintf(buf,"AAAAAAGGGGGHHHHH!!!!");
  do_yell(victim, buf);
  
  obj = create_object(get_obj_index(OBJ_VNUM_SEVERED_HEAD),ch->level);
  
  sprintf(buf, obj->short_descr, victim->name);
  free_string( obj->short_descr );
  obj->short_descr = str_dup( buf );
  
  sprintf(buf, obj->description, victim->name);
  free_string( obj->description );
  obj->description = str_dup( buf );
  
  obj_to_char(obj, ch);
  
  act("You slice off $N's head and place it in a bag.",ch,NULL,victim,TO_CHAR);
  act("$n slices off $N's head and places it in a bag.",ch,NULL,victim,TO_NOTVICT);
  act("$n slices off your head!",ch,NULL,victim,TO_VICT);
  act("$n's headless body twitches violently.",victim,NULL,NULL,TO_ROOM);
  act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
  send_to_char( "You have been `1KILLED`` by a Bounty Hunter!\n\r",victim );

  fulfill_bounty( ch, victim, IS_NULLSTR( argument ) ? "1" : argument );
  
  _raw_kill( ch, victim, FALSE );
  affect_strip(ch, skill_lookup("analyze"));
}


/* checks if a given bounty has allied priority when looked at by pCabal */
CABAL_DATA* is_bounty_priority( BOUNTY_DATA* bounty, CABAL_DATA* pCabal ){
  CABAL_DATA* pCab = get_parent( pCabal );
  BBID_DATA* bbid;

  if (bounty == NULL || pCab == NULL)
    return NULL;
  else if (!IS_CABAL(pCab, CABAL_ROUGE) || !IS_CABAL(pCab, CABAL_ALLIANCE))
    return NULL;

  /* check bids in the bounty for alliances with this rouge cabal */
  for (bbid = bounty->bids; bbid; bbid = bbid->next ){
    if (bbid->pCabal && IS_CABAL(bbid->pCabal, CABAL_ALLIANCE) && get_parent(bbid->pCabal) != pCab 
	&& get_pact(bbid->pCabal, pCab, PACT_ALLIANCE, FALSE) != NULL)
      return bbid->pCabal;
  }
  return NULL;
}

/* checks if given character can be covered by any rouge cabal memebers */
bool bounty_covered( CHAR_DATA* victim ){
  if (IS_NPC(victim) || victim->pcdata->pbounty == NULL)
    return TRUE;
  else{
    CHAR_DATA* vch;
    for (vch = player_list; vch; vch = vch->next_player){
      if (vch->pCabal && !IS_IMMORTAL(vch) && IS_CABAL(vch->pCabal, CABAL_ROUGE)
	  && is_pk_abs(vch, victim))
	return TRUE;
    }
    return FALSE;
  }
}
  

/* command used to get a contract on a bounty rouge cabals cannot cover */
void do_contract( CHAR_DATA* ch, char* argument ){
  CHAR_DATA* vch;
  CHAR_DATA* mob;
  int count = 0;
  
  if (ch->pCabal && IS_CABAL(ch->pCabal, CABAL_ROUGE)){
    send_to_char("Use \"who bounty\" to see bounties avaliable.\n\r", ch);
    return;
  }
  for (mob = ch->in_room->people; mob; mob = mob->next_in_room ){
    if (IS_NPC(mob) && IS_SET(mob->act, ACT_CONTRACTER))
      break;
  }

  if (IS_NULLSTR(argument)){
    bool fFound = FALSE;
    send_to_char("Following bounties can be contracted out to you:\n\r", ch );
    for (vch = player_list; vch; vch = vch->next_player){
      if (vch->pcdata->pbounty && vch != ch && is_pk_abs(ch, vch) 
	  && can_see(ch, vch) && !bounty_covered( vch )){
	sendf( ch, "%2d. %s\n\r", ++count, vch->name);
	fFound = TRUE;
      }
    }
    if (!fFound)
      send_to_char("None.\n\r", ch);
    return;
  }
  else if (is_affected(ch, gen_contract)){
    send_to_char("You are still bound by previous contract.\n\r", ch);
    return;
  }
  else if ( (vch = get_char_world( ch, argument)) == NULL){
    send_to_char("They do not seem to be present.\n\r", ch );
    return;
  }
  else if (ch == vch){
    send_to_char("You cannot contract yourself.\n\r", ch);
    return;
  }
  else if (bounty_covered( vch) || !is_pk_abs(ch, vch)){
    send_to_char("Their bounty is not avaliable to be contracted out by you.\n\r", ch);
    return;
  }
  else{
    AFFECT_DATA af, *paf;
    
    af.type	= gen_contract;
    af.level	= ch->level;
    af.duration	= 72;
    
    af.where	= TO_AFFECTS;
    af.bitvector= 0;
    af.location	= APPLY_NONE;
    af.modifier	= FALSE;

    paf = affect_to_char( ch, &af );
    string_to_affect( paf, vch->name );

    if (mob ){
      act("$N tells you 'You have 72 hours to do the deed, or until someone becomes avaliable.'", ch, NULL, mob, TO_CHAR);
      act("$N nods ever so slightly and turns $S back on $n.", ch, NULL, mob, TO_ROOM);
    }
    else{
      send_to_char("There is no one here to take your contract.\n\r", ch);
    }
  }
}

/* checks if the person can collect the bounty */
bool can_collect( BOUNTY_DATA* bounty, CHAR_DATA* ch ){
  CHAR_DATA* och = ch;
  AFFECT_DATA* paf;

  if (IS_NPC(ch) && ch->master)
    och = ch->master;
  else if (IS_NPC(ch) && ch->leader)
    och = ch->leader;

  if (IS_NPC(och) || bounty == NULL)
    return FALSE;
  else if ( och->pCabal != NULL && IS_CABAL(och->pCabal, CABAL_ROUGE) )
    return TRUE;
  else if ( (paf =  affect_find(och->affected, gen_contract)) != NULL 
	    && paf->has_string 
	    && !IS_NULLSTR(paf->string) 
	    && is_name(paf->string, bounty->name)){
    return TRUE;
  }
  else
    return FALSE;
}
	    
bool check_rouge_bounty( CHAR_DATA* och, int pen ){
  CHAR_DATA* ch = och;
  CHAR_DATA* vch;
  CABAL_DATA* pc; 
  char buf[MIL];
  int sn = skill_lookup("analyze");

  if (IS_NPC(och) && och->master)
    ch = och->master;

  if (ch->pCabal == NULL || !IS_CABAL(ch->pCabal, CABAL_ROUGE))
    return FALSE;
  else 
    pc = get_parent( ch->pCabal);

/* penalty for not collecting bounties */
  for (vch = player_list; vch; vch = vch->next_player){
    if (vch->pcdata->pbounty 
	&& !is_affected(vch, gsn_noquit )
	&& can_see(ch, vch) 
	&& is_pk(ch, vch)
	&& can_collect(vch->pcdata->pbounty, ch))
      break;
  }
  
  return (vch != NULL);

/* Viri: no longer used */
  if (vch != NULL){
    AFFECT_DATA *paf;
    int strike = 0;

    // give them three strikes 
    if ( (paf = affect_find(ch->affected, sn)) == NULL){
      AFFECT_DATA af;

      af.type	= sn;
      af.level	= 60;
      af.duration = -1;
      af.where = TO_NONE;
      af.bitvector = 0;
      af.location	= APPLY_NONE;
      af.modifier = 1;
      affect_to_char(ch, &af);
      strike = 1;
    }
    else{
      paf->modifier++;
      strike = paf->modifier;
    }

    if (strike > 3){
      pen = (strike - 3) * pen;
      strike++;
      sprintf( buf, "%s has ignored a bounty!", ch->name);
      cabal_echo( pc, buf );
      distribute_cps(ch, ch->pCabal, pen * CPTS, TRUE );
    
      // if person is out of cps we demote them 
      // we subtract the gain since reward takes effect on tick, not instantenously 
      if ((GET_CP( ch ) < 1) && ch->pcdata->rank > RANK_NEWBIE ){
	char sub[MIL];
	sprintf( buf, "Due to disregard for bounties, %s has been demoted.", PERS2(ch) );
	cabal_echo( pc, buf );
	strcat( buf, "\n\r");
	sprintf( sub, "%s's demotion.", PERS2(ch));
	do_hal( pc->name, sub, buf, NOTE_NEWS );
	promote( ch, ch->pCabal, -1 );
	if (ch->pcdata->member)
	  ch->pcdata->member->time_stamp = mud_data.current_time;
      }
    }
    else{
      sprintf( buf, "%s can ignore %d more %s.", 
	       ch->name,
	       (3 - strike),
	       (3 - strike) == 1 ? "bounty" : "bounties");
      cabal_echo( pc, buf );      
    }
    return TRUE;
  }
  else
    affect_strip(ch, sn );
  return FALSE;
}