#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "recycle.h"
#include "obj_trig.h"

extern bool ch_is_quitting;
extern OBJ_TRIG *ot_list;
extern OBJ_TRIG *giant_ot_list;
extern OBJ_TRIG *on_tick_ot_list;
//extern OBJ_TRIG_DATA *obj_trig_list;
void free_ot(OBJ_TRIG *ot);
void free_trap (TRAP_DATA * trap);
OBJ_TRIG *new_ot(int vnum);

/* stuff for recyling notes */
NOTE_DATA *note_free;
NOTE_DATA *new_note ()
{
  NOTE_DATA *note;
  if (note_free == NULL)
    note = alloc_perm (sizeof (*note));

  else
    {
      note = note_free;
      note_free = note_free->next;
    }
  VALIDATE (note);
  return note;
}

void free_note (NOTE_DATA * note)
{
  if (!IS_VALID (note))
    return;
  free_string (note->text);
  free_string (note->subject);
  free_string (note->to_list);
  free_string (note->date);
  free_string (note->sender);
  INVALIDATE (note);
  note->next = note_free;
  note_free = note;
}


/* stuff for recycling ban structures */
BAN_DATA *ban_free;
BAN_DATA *new_ban (void)
{
  static BAN_DATA ban_zero;
  BAN_DATA *ban;
  if (ban_free == NULL)
    ban = alloc_perm (sizeof (*ban));

  else
    {
      ban = ban_free;
      ban_free = ban_free->next;
    }
  *ban = ban_zero;
  VALIDATE (ban);
  ban->name = &str_empty[0];
  return ban;
}

void free_ban (BAN_DATA * ban)
{
  if (!IS_VALID (ban))
    return;
  free_string (ban->name);
  INVALIDATE (ban);
  ban->next = ban_free;
  ban_free = ban;
}


/* stuff for recycling descriptors */
DESCRIPTOR_DATA *descriptor_free;
DESCRIPTOR_DATA *new_descriptor (void)
{
  static DESCRIPTOR_DATA d_zero;
  DESCRIPTOR_DATA *d;
  if (descriptor_free == NULL)
    d = alloc_perm (sizeof (*d));

  else
    {
      d = descriptor_free;
      descriptor_free = descriptor_free->next;
    }
  *d = d_zero;
  VALIDATE (d);
  return d;
}

void free_descriptor (DESCRIPTOR_DATA * d)
{
  if (!IS_VALID (d))
    return;
  free_string (d->host);
  free_mem (d->outbuf, d->outsize);
  INVALIDATE (d);
  d->next = descriptor_free;
  descriptor_free = d;
}


/* stuff for recycling gen_data */
GEN_DATA *gen_data_free;
GEN_DATA *new_gen_data (void)
{
  static GEN_DATA gen_zero;
  GEN_DATA *gen;
  if (gen_data_free == NULL)
    gen = alloc_perm (sizeof (*gen));

  else
    {
      gen = gen_data_free;
      gen_data_free = gen_data_free->next;
    }
  *gen = gen_zero;
  VALIDATE (gen);
  return gen;
}

void free_gen_data (GEN_DATA * gen)
{
  if (!IS_VALID (gen))
    return;
  INVALIDATE (gen);
  gen->next = gen_data_free;
  gen_data_free = gen;
}


/* stuff for recycling extended descs */
EXTRA_DESCR_DATA *extra_descr_free;
EXTRA_DESCR_DATA *new_extra_descr (void)
{
  EXTRA_DESCR_DATA *ed;
  if (extra_descr_free == NULL)
    ed = alloc_perm (sizeof (*ed));

  else
    {
      ed = extra_descr_free;
      extra_descr_free = extra_descr_free->next;
    }
  ed->keyword = &str_empty[0];
  ed->description = &str_empty[0];
  VALIDATE (ed);
  return ed;
}

void free_extra_descr (EXTRA_DESCR_DATA * ed)
{
  if (!IS_VALID (ed))
    return;
  free_string (ed->keyword);
  free_string (ed->description);
  INVALIDATE (ed);
  ed->next = extra_descr_free;
  extra_descr_free = ed;
}


/* stuff for recycling affects */
AFFECT_DATA *affect_free;
AFFECT_DATA *new_affect (void)
{
  static AFFECT_DATA af_zero;
  AFFECT_DATA *af;
  if (affect_free == NULL)
    af = alloc_perm (sizeof (*af));

  else
    {
      af = affect_free;
      affect_free = affect_free->next;
    }
  *af = af_zero;
  af->comp_name = str_dup ("");
  af->permaff = FALSE;
  af->composition = FALSE;
  VALIDATE (af);
  return af;
}

void free_affect (AFFECT_DATA * af)
{
  if (!IS_VALID (af))
    return;
  if (af->comp_name != NULL)
    free_string (af->comp_name);
  INVALIDATE (af);
  af->next = affect_free;
  affect_free = af;
}

SCENT_DATA *scent_free;
MEMORY_DATA *memory_free;
COMP_DATA *comp_free;

/* stuff for recycling objects */
OBJ_DATA *obj_free;
OBJ_DATA *new_obj (void)
{
  static OBJ_DATA obj_zero;
  OBJ_DATA *obj;
  if (obj_free == NULL)
    obj = alloc_perm (sizeof (*obj));

  else
    {
      obj = obj_free;
      obj_free = obj_free->next;
    }
  *obj = obj_zero;
  VALIDATE (obj);
  return obj;
}

TRAP_DATA *trap_free;
TRAP_DATA *new_trap (void)
{
  static TRAP_DATA trap_zero;
  TRAP_DATA *trap;
  if (trap_free == NULL)
    trap = alloc_perm (sizeof (*trap));

  else
    {
      trap = trap_free;
      trap_free = trap_free->next;
    }
  *trap = trap_zero;
  VALIDATE (trap);
  // Don't know if these two lines are necessary but I'm paranoid, Paarsh
  trap->dammessage = str_dup ("");
  trap->owner = str_dup ("");
  return trap;
}

/*BLADE_SPELL_DATA *bs_free;
BLADE_SPELL_DATA *new_blade_spell(void)
{
   static BLADE_SPELL_DATA bs_zero;
   BLADE_SPELL_DATA *bs;
   if(bs_free == NULL)
      bs = alloc_perm(sizeof(*bs));
   else
   {
      bs = bs_free;
      bs_free = bs_free->next;
   }

   *bs = bs_zero;
   VALIDATE(bs);

   return bs;
} */
SCENT_DATA *new_scent (void)
{
  static SCENT_DATA scent_zero;
  SCENT_DATA *scent;
  if (scent_free == NULL)
    scent = alloc_perm (sizeof (*scent));

  else
    {
      scent = scent_free;
      scent_free = scent_free->next;
    }
  *scent = scent_zero;
  return (scent);
}

COMP_DATA *new_comp (void)
{
  static COMP_DATA comp_zero;
  COMP_DATA *comp;
  if (comp_free == NULL)
    comp = alloc_perm (sizeof (*comp));

  else
    {
      comp = comp_free;
      comp_free = comp_free->next;
    }
  *comp = comp_zero;
  comp->name = NULL;
  comp->title = NULL;
  comp->next = NULL;
  comp->type = 0;
  comp->skill = 0;
  return (comp);
}

MEMORY_DATA *new_memory (void)
{
  static MEMORY_DATA memory_zero;
  MEMORY_DATA *memd;
  if (memory_free == NULL)
    memd = alloc_perm (sizeof (*memd));

  else
    {
      memd = memory_free;
      memory_free = memory_free->next;
    }
  *memd = memory_zero;
  memd->player = NULL;
  memd->mob = NULL;
  memd->next = NULL;
  memd->next_memory = NULL;
  return (memd);
}


void free_obj (OBJ_DATA * obj)
{
  AFFECT_DATA *paf, *paf_next;
  EXTRA_DESCR_DATA *ed, *ed_next;
  int i;
  if (!IS_VALID (obj))
    return;
  for (paf = obj->affected; paf != NULL; paf = paf_next)
    {
      paf_next = paf->next;
      free_affect (paf);
    }
  obj->affected = NULL;
  for (ed = obj->extra_descr; ed != NULL; ed = ed_next)
    {
      ed_next = ed->next;
      free_extra_descr (ed);
    }
  obj->extra_descr = NULL;
  free_string (obj->name);
  free_string (obj->description);
  free_string (obj->short_descr);
  free_string (obj->owner);
  if (obj->plr_owner)
    free_string (obj->plr_owner);
  //Iblis 12-31-03 Object triggers
  for (i=0;i<MAX_OBJ_TRIGS;i++)
  {
    if (obj->objtrig[i])
    {
      obj->objtrig[i]->obj_on = NULL;
      free_ot(obj->objtrig[i]);
      obj->objtrig[i] = NULL;
    }
  }
  INVALIDATE (obj);
  obj->next = obj_free;
  obj_free = obj;
}

void free_trap (TRAP_DATA * trap)
{
  if (!IS_VALID (trap))
	return;
  
  free_string (trap->owner);
  free_string (trap->dammessage);
  INVALIDATE (trap);
  trap->next = trap_free;
  trap_free = trap;
}

/*void free_blade_spell (BLADE_SPELL_DATA *bs)
{
   int i;
   if(!IS_VALID(bs))
      return;

   for(i = 0; i < MAX_BLADE_SPELLS; i++)
   {
      bs->capacity[i] = 0;
      bs->charges[i] = 0;
      bs->level[i] = 0;
   }
   INVALIDATE(bs);
   bs->next = bs_free;
   bs_free = bs;
} */
void free_scent (SCENT_DATA * sc)
{
  sc->player = NULL;
  sc->next_in_room = NULL;
  sc->in_room = NULL;
  sc->next = scent_free;
  scent_free = sc;
}

void free_memory (MEMORY_DATA * memd)
{
  memd->player = NULL;
  memd->mob = NULL;
  memd->next_memory = NULL;
  memd->next = memory_free;
  memory_free = memd;
}

void free_comp (COMP_DATA * comp)
{
  comp->name = NULL;
  comp->title = NULL;
  comp->type = 0;
  comp->skill = 0;
  comp->next = comp_free;
  comp_free = comp;
}

/* stuff for recyling characters */
CHAR_DATA *char_free;
FAKE_DATA *fake_free;
FAKE_DATA *new_fake (void)
{
  static FAKE_DATA fake_zero;
  FAKE_DATA *fd;
  if (fake_free == NULL)
    fd = alloc_perm (sizeof (*fd));

  else
    {
      fd = fake_free;
      fake_free = fake_free->next;
    }
  *fd = fake_zero;
  fd->name = &str_empty[0];
  fd->title = &str_empty[0];
  fd->race = 0;
  fd->class = 0;
  fd->level = 0;
  fd->descriptor = 0;
  fd->next = NULL;
  return fd;
}

CHAR_DATA *new_char (void)
{
  static CHAR_DATA ch_zero;
  CHAR_DATA *ch;
  int i;
  if (char_free == NULL)
    ch = alloc_perm (sizeof (*ch));

  else
    {
      ch = char_free;
      char_free = char_free->next;
    }
  *ch = ch_zero;
  VALIDATE (ch);
  ch->name = &str_empty[0];
  ch->short_descr = &str_empty[0];
  ch->long_descr = &str_empty[0];
  ch->description = &str_empty[0];
  ch->prompt = &str_empty[0];
  ch->prefix = &str_empty[0];
  ch->tracking = &str_empty[0];
  ch->duel = &str_empty[0];
  ch->afkmsg = str_dup ("");
  ch->next_in_board = NULL;
  ch->logon = current_time;
  ch->lines = PAGELEN;
  for (i = 0; i < 4; i++)
    ch->armor[i] = 100;
  ch->position = POS_STANDING;
  ch->hit = 20;
  ch->max_hit = 20;
  ch->mana = 100;
  ch->max_mana = 100;
  ch->move = 100;
  ch->max_move = 100;
  ch->stunned = 0;
  for (i = 0; i < MAX_STATS; i++)
    {
      ch->perm_stat[i] = 13;
      ch->mod_stat[i] = 0;
    }
  ch->contaminator = NULL;
  return ch;
}

void free_fake (FAKE_DATA * fd)
{
  free_string (fd->name);
  free_string (fd->title);
  fd->next = fake_free;
  fake_free = fd;
}

void free_char (CHAR_DATA * ch)
{
  OBJ_DATA *obj;
  OBJ_DATA *obj_next;
  AFFECT_DATA *paf;
  AFFECT_DATA *paf_next;
  TRIGGER_DATA *trigger, *trig_next;
  SCRIPT_DATA *scr, *scr_next;
  ROOM_INDEX_DATA *old_room;
  if (!IS_VALID (ch))
    return;
  if (IS_NPC (ch))
    {
      mobile_count--;
      for (trigger = ch->triggers; trigger != NULL; trigger = trig_next)
	{
	  trig_next = trigger->next;
	  free_string (trigger->keywords);
	  free_string (trigger->name);
	  for (scr = trigger->script; scr != NULL; scr = scr_next)
	    {
	      scr_next = scr->next;
	      if (scr->command != NULL)
		free_string (scr->command);
	      free (scr);
	    }
	  free (trigger);
	}
    }
  //10/05/03 Iblis - Added a super cheap set to fix the age old linkdead duping weilding bug
  ch_is_quitting = TRUE; //Set so that the message of dropping item won't appear
  old_room = ch->in_room;
  ch->in_room = get_room_index(1);
  for (obj = ch->carrying; obj != NULL; obj = obj_next)
    {
      obj_next = obj->next_content;
      extract_obj (obj);
    }
  ch->in_room = old_room;
  ch_is_quitting = FALSE;
  for (paf = ch->affected; paf != NULL; paf = paf_next)
    {
      paf_next = paf->next;
      affect_remove (ch, paf);
    }
  free_string (ch->name);
  free_string (ch->short_descr);
  free_string (ch->long_descr);
  free_string (ch->description);
  free_string (ch->prompt);
  free_string (ch->prefix);
  free_string (ch->tracking);
  if (ch->sword != NULL)
  {
    log_string("Extracting ch->sword from");
    log_string(ch->name);
    extract_obj (ch->sword);
  }
  if (ch->mask != NULL)
    free_string (ch->mask);
  if (ch->pcdata != NULL)
    free_pcdata (ch->pcdata);
  ch->next = char_free;
  char_free = ch;
  INVALIDATE (ch);
  return;
}

PC_DATA *pcdata_free;
PC_DATA *new_pcdata (void)
{
  short x;
  static PC_DATA pcdata_zero;
  PC_DATA *pcdata;
  if (pcdata_free == NULL)
    pcdata = alloc_perm (sizeof (*pcdata));

  else
    {
      pcdata = pcdata_free;
      pcdata_free = pcdata_free->next;
    }
  *pcdata = pcdata_zero;
  for (x = 0; x < MAX_ALIAS; x++)
    {
      pcdata->alias[x] = NULL;
      pcdata->alias_sub[x] = NULL;
    }
  for (x = 0; x < MAX_HISTORY; x++)
    pcdata->history[x] = NULL;
  pcdata->buffer = new_buf ();
  pcdata->boarded = NULL;
  VALIDATE (pcdata);
  return pcdata;
}

void free_pcdata (PC_DATA * pcdata)
{
  short x;
  if (!IS_VALID (pcdata))
    return;
  free_string (pcdata->pwd);
  free_string (pcdata->bamfin);
  free_string (pcdata->speedwalk);
  free_string (pcdata->bamfout);
  free_string (pcdata->whoinfo);
  free_string (pcdata->pretitle);
  free_string (pcdata->battlecry);
  free_string (pcdata->plan);
  free_string (pcdata->title);
  free_string (pcdata->restoremsg);
  free_string (pcdata->email_addr);
  if (pcdata->buffer != NULL)
    free_buf (pcdata->buffer);
  for (x = 0; x < MAX_ALIAS; x++)
    {
      free_string (pcdata->alias[x]);
      free_string (pcdata->alias_sub[x]);
    }
  for (x = 0; x < MAX_HISTORY; x++)
    free_string (pcdata->history[x]);
  free_string (pcdata->familiar_name);
  if (pcdata->familiar)
    extract_char(pcdata->familiar, TRUE);
  INVALIDATE (pcdata);
  pcdata->next = pcdata_free;
  pcdata_free = pcdata;
  return;
}


/* stuff for recycling bounties */
BOUNTY_DATA *bounty_free;
BOUNTY_DATA *new_bounty (void)
{
  static BOUNTY_DATA b_zero;
  BOUNTY_DATA *b;
  if (bounty_free == NULL)
    b = alloc_perm (sizeof (*b));

  else
    {
      b = bounty_free;
      bounty_free = bounty_free->next;
    }
  *b = b_zero;
  VALIDATE (b);
  return b;
}

void free_bounty (BOUNTY_DATA * b)
{
  if (!IS_VALID (b))
    return;
  free_string (b->name);
  INVALIDATE (b);
  b->next = bounty_free;
  bounty_free = b;
}


/* stuff for recycling inventions */
INVENTION_DATA *invention_free;
INVENTION_DATA *new_invention (void)
{
  static INVENTION_DATA b_zero;
  INVENTION_DATA *b;
  if (invention_free == NULL)
    b = alloc_perm (sizeof (*b));

  else
    {
      b = invention_free;
      invention_free = invention_free->next;
    }
  *b = b_zero;
  VALIDATE (b);
  return b;
}

void free_invention (INVENTION_DATA * b)
{
  if (!IS_VALID (b))
    return;

  //  free_string( b->name );
  INVALIDATE (b);
  b->next = invention_free;
  invention_free = b;
}


/* stuff for recycling aggressor_lists */
AGGRESSOR_LIST *aggressor_list_free;
AGGRESSOR_LIST *new_aggressor (void)
{
  static AGGRESSOR_LIST b_zero;
  AGGRESSOR_LIST *b;
  if (aggressor_list_free == NULL)
    b = alloc_perm (sizeof (*b));

  else
    {
      b = aggressor_list_free;
      aggressor_list_free = aggressor_list_free->next;
    }
  *b = b_zero;
  VALIDATE (b);
  return b;
}

void free_aggressor_list (AGGRESSOR_LIST * b)
{
  if (!IS_VALID (b))
    return;

  //  free_string( b->name );
  INVALIDATE (b);

  //Iblis 6/28/03 - I take char of pointers in the places this is called..that was just easier
  b->next = aggressor_list_free;
  aggressor_list_free = b;
}


/* stuff for setting ids */
long last_pc_id;
long last_mob_id;
long get_pc_id (void)
{
  int val;
  val = (current_time <= last_pc_id) ? last_pc_id + 1 : current_time;
  last_pc_id = val;
  return val;
}

long get_mob_id (void)
{
  last_mob_id++;
  return last_mob_id;
}

BUFFER *buf_free;
const int buf_size[MAX_BUF_LIST] =
  { 16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768, 65536
};

/* local procedure for finding the next acceptable size */
/* -1 indicates out-of-boundary error */
int get_size (int val)
{
  int i;
  for (i = 0; i < MAX_BUF_LIST; i++)
    if (buf_size[i] >= val)
      {
	return buf_size[i];
      }
  return -1;
}

BUFFER *new_buf ()
{
  BUFFER *buffer;
  if (buf_free == NULL)
    buffer = alloc_perm (sizeof (*buffer));

  else
    {
      buffer = buf_free;
      buf_free = buf_free->next;
    }
  buffer->next = NULL;
  buffer->state = BUFFER_SAFE;
  buffer->size = get_size (BASE_BUF);
  buffer->string = alloc_mem (buffer->size);
  buffer->string[0] = '\0';
  VALIDATE (buffer);
  return buffer;
}

BUFFER *new_buf_size (int size)
{
  BUFFER *buffer;
  if (buf_free == NULL)
    buffer = alloc_perm (sizeof (*buffer));

  else
    {
      buffer = buf_free;
      buf_free = buf_free->next;
    }
  buffer->next = NULL;
  buffer->state = BUFFER_SAFE;
  buffer->size = get_size (size);
  if (buffer->size == -1)
    {
      bug ("new_buf: buffer size %d too large.", size);
      exit (1);
    }
  buffer->string = alloc_mem (buffer->size);
  buffer->string[0] = '\0';
  VALIDATE (buffer);
  return buffer;
}

void free_buf (BUFFER * buffer)
{
  if (!IS_VALID (buffer) || buffer == NULL)
    return;
  free_mem (buffer->string, buffer->size);
  buffer->string = NULL;
  buffer->size = 0;
  buffer->state = BUFFER_FREED;
  INVALIDATE (buffer);
  buffer->next = buf_free;
  buf_free = buffer;
}

bool add_buf (BUFFER * buffer, char *string)
{
	int len;
	char *oldstr;
	int oldsize;
	oldstr = buffer->string;
	oldsize = buffer->size;
	if (buffer->state == BUFFER_OVERFLOW)	/* don't waste time on bad strings! */
		return FALSE;
	len = strlen (buffer->string) + strlen (string) + 1;
	while (len >= buffer->size)
	{				/* increase the buffer size */
		buffer->size = get_size (buffer->size + 1);
		{
			if (buffer->size == -1)
			{			/* overflow */
				buffer->size = oldsize;
				buffer->state = BUFFER_OVERFLOW;
				bug ("buffer overflow past size %d", buffer->size);
				return FALSE;
			}
		}
	}
	if (buffer->size != oldsize)
	{
		buffer->string = alloc_mem (buffer->size);
		strcpy (buffer->string, oldstr);
		free_mem (oldstr, oldsize);
	}
	strcat (buffer->string, string);
	return TRUE;
}

void clear_buf (BUFFER * buffer)
{
  buffer->string[0] = '\0';
  buffer->state = BUFFER_SAFE;
}

char *buf_string (BUFFER * buffer)
{
  return buffer->string;
}



OBJ_TRIG_DATA *obj_trig_free;

OBJ_TRIG_DATA *new_obj_trig(void)
{
	static OBJ_TRIG_DATA obj_trig_zero;
	OBJ_TRIG_DATA *ot;
	int i;

	if(obj_trig_free == NULL)
		ot = alloc_perm(sizeof(*ot));
	else
	{
		ot = obj_trig_free;
		obj_trig_free = obj_trig_free->next;
	}

	*ot = obj_trig_zero;
	VALIDATE(ot);
	ot->trig_flags = 0;
	ot->trigger = NULL;
	ot->extra_flags = 0;
	for (i=0;i<16;i++)
	{
	  ot->action[i] = NULL;
	  ot->chance[i] = 0;
	  ot->delay[i] = 0;
	}
	ot->overall_chance = 100;
//	for(i = 0; i < MAX_OBJ_TRIG_PARENTS; i++)
//		ot->parent[i] = 0;

	return ot;
}

void free_obj_trig(OBJ_TRIG_DATA *ot)
{
	int i=0;

	if(ot == NULL || !IS_VALID(ot))
		return;

	free_string(ot->trigger);
	for (i=0;i<16;i++)
  	  free_string(ot->action[i]);
	

	INVALIDATE(ot);

	ot->next = obj_trig_free;
	obj_trig_free = ot;
}

OBJ_TRIG *ot_free;

OBJ_TRIG *new_ot(int vnum)
{
  static OBJ_TRIG ot_zero;
  OBJ_TRIG *ot;
  OBJ_TRIG_DATA *otd;

  otd = get_obj_trig (vnum);
  if (otd == NULL)
  {
    bug("when creating ot, Object Trigger vnum -> %d not found",vnum);
    return NULL;
  }
  if(ot_free == NULL)
    ot = alloc_perm(sizeof(*ot));
  else
  {
    ot = ot_free;
    ot_free = ot_free->next;
  }

  *ot = ot_zero;
  VALIDATE(ot);
/*  ot->trig_flags = 0;
  ot->trigger = NULL;
  for (i=0;i<16;i++)
    {
      ot->action[i] = NULL;
      ot->chance[i] = 0;
      ot->delay[i] = 0;
    }
  for(i = 0; i < MAX_OBJ_TRIG_PARENTS; i++)
    ot->parent[i] = 0;*/
//  ot->next = ot_list;
//  ot_list = ot;
  ot->next = NULL;
  ot->next_on_tick = NULL;
  ot->statement_on = 0;
  ot->seconds_left = 0;
  ot->pIndexData = otd;
  ot->obj_on = NULL;
/*  if(IS_SET(ot->pIndexData->trig_flags, OBJ_TRIG_CHAR_TO_ROOM))
  {
    ot->next_on_tick = on_tick_ot_list;
    on_tick_ot_list = ot;
  }
  else ot->next_on_tick = NULL;*/
  ot->next_ot = giant_ot_list;
  giant_ot_list = ot;
  if (IS_SET(otd->trig_flags,OBJ_TRIG_ON_TICK))
  {
    ot->next_on_tick = on_tick_ot_list;
    on_tick_ot_list = ot;
  }
      
  return ot;
}

void free_ot(OBJ_TRIG *ot)
{
	OBJ_TRIG *otp;
	bool found=FALSE;
	int i,k;
	

	if(ot == NULL || !IS_VALID(ot))
          return;
	if ((ot->next != NULL || ot->statement_on != 0 || ot->seconds_left != 0) && ot_list != NULL)
	{
	  if (ot_list == ot)
	    ot_list = ot->next;
	  else if (ot_list->next == ot)
	    ot_list->next = ot->next;
	  else 
  	  {
	    for (otp = ot_list;otp->next != NULL;otp = otp->next)
	    {
	      if (otp->next == ot)
	      {
	        otp->next = ot->next;
	        found = TRUE;
	        break;
	      }
	    }
	    if (!found)
	    {
  	      bug("object trigger to be freed NOT FOUND.",0);
	      //if (ot->obj_on)
	      //  ot->obj_on->objtrig = NULL;
	//      return;
	    }
	  }
	}
	if (on_tick_ot_list != NULL)
	{
	 if (on_tick_ot_list == ot)
	  on_tick_ot_list = ot->next_on_tick;
	 else if (on_tick_ot_list->next_on_tick == ot)
	  on_tick_ot_list->next_on_tick = ot->next_on_tick;
          else
            {
              for (otp = on_tick_ot_list;otp->next_on_tick != NULL;otp = otp->next_on_tick)
                {
                  if (otp->next_on_tick == ot)
                    {
                      otp->next_on_tick = ot->next_on_tick;
                      found = TRUE;
                      break;
                    }
                }
/*              if (!found)
                {
                  bug("object trigger to be freed NOT FOUND on on_tick_ot_list.",0);
                  //if (ot->obj_on)
                  //  ot->obj_on->objtrig = NULL;
                  return;
                }*/
            }
	}

        found = FALSE;
	ot->pIndexData = NULL;
	    if (giant_ot_list == ot)
	      giant_ot_list = ot->next_ot;
	    else if (giant_ot_list->next_ot == ot)
	      giant_ot_list->next_ot = ot->next_ot;
          else
	    {
	      for (otp = giant_ot_list;otp->next_ot != NULL;otp = otp->next_ot)
		{
		  if (otp->next_ot == ot)
		    {
		      otp->next_ot = ot->next_ot;
		      found = TRUE;
		      break;
		    }
		}
	      if (!found)
		{
		  bug("object trigger to be freed NOT FOUND on giant_ot list.",0);
		  //if (ot->obj_on)
		  //  ot->obj_on->objtrig = NULL;
//		  return;
		}
	    }

	if (ot->obj_on)
	{
 	  for (i=0;i<MAX_OBJ_TRIGS;i++)
	  {
  	    if (ot->obj_on->objtrig[i] == ot)
	    {
	      for(k=i;k<MAX_OBJ_TRIGS-1;k++)
	        ot->obj_on->objtrig[k] = ot->obj_on->objtrig[k+1];
	      ot->obj_on->objtrig[MAX_OBJ_TRIGS-1] = NULL;
	    }
	  }
	}
	ot->obj_on = NULL;
	INVALIDATE(ot);
	ot->next = ot_free;
	ot_free = ot;
}

/* Iblis - 8/30/04 - stuff for recycling rune_card data */
RUNE_CARD_DATA *rune_card_free;
RUNE_CARD_DATA *new_rune_card (void)
{
  static RUNE_CARD_DATA b_zero;
  RUNE_CARD_DATA *b;
  if (rune_card_free == NULL)
    b = alloc_perm (sizeof (*b));

  else
    {
      b = rune_card_free;
      rune_card_free = rune_card_free->next;
    }
  *b = b_zero;
  VALIDATE (b);
  return b;
}

void free_rune_card (RUNE_CARD_DATA * b)
{
  if (!IS_VALID (b))
    return;

  //  free_string( b->name );
  INVALIDATE (b);
  b->next = rune_card_free;
  rune_card_free = b;
}