/* $Id: recycle.c,v 1.666 2004/09/20 10:49:52 shrike Exp $ */
/************************************************************************************
* Copyright 2004 Astrum Metaphora consortium *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* *
************************************************************************************/
/************************************************************************************
* ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR *
* ANATOLIA has been brought to you by ANATOLIA consortium *
* Serdar BULUT {Chronos} bulut@rorqual.cc.metu.edu.tr *
* Ibrahim Canpunar {Asena} canpunar@rorqual.cc.metu.edu.tr *
* Murat BICER {KIO} mbicer@rorqual.cc.metu.edu.tr *
* D.Baris ACAR {Powerman} dbacar@rorqual.cc.metu.edu.tr *
* By using this code, you have agreed to follow the terms of the *
* ANATOLIA license, in the file Anatolia/anatolia.licence *
***********************************************************************************/
/************************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
************************************************************************************/
/************************************************************************************
* ROM 2.4 is copyright 1993-1995 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@pacinfo.com) *
* Gabrielle Taylor (gtaylor@pacinfo.com) *
* Brian Moore (rom@rom.efn.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
*************************************************************************************/
/************************************************************************************
* Copyright (c) 1998 fjoe <fjoe@iclub.nsu.ru> *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND *
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE *
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS *
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) *
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *
* SUCH DAMAGE. *
************************************************************************************/
#include <sys/types.h>
// Welesh : compat
#if !defined (WIN32)
#include <sys/time.h>
#include <regex.h>
#else
#include "compat\regex-win32\regex.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "db/db.h"
/* stuff for recycling extended descs */
extern int top_ed;
extern void free_contacts(CHAR_DATA *ch);
extern void nuke_slaves (CHAR_DATA *ch);
ED_DATA *ed_new(void)
{
ED_DATA *ed;
ed = calloc(1, sizeof(*ed));
top_ed++;
return ed;
}
ED_DATA *ed_new2(const ED_DATA *ed, const char* name)
{
ED_DATA *ed2 = ed_new();
ed2->keyword = str_dup(ed->keyword);
ed2->description = mlstr_printf(ed->description, name);
return ed2;
}
ED_DATA *ed_dup(const ED_DATA *ed)
{
ED_DATA *ned = ed_new();
ned->keyword = str_dup(ed->keyword);
ned->description = mlstr_dup(ed->description);
return ned;
}
void ed_free(ED_DATA *ed)
{
if (!ed)
return;
free_string(ed->keyword);
mlstr_free(ed->description);
free(ed);
top_ed--;
}
void ed_fread(FILE *fp, ED_DATA **edp)
{
ED_DATA *ed = ed_new();
ed->keyword = fread_string(fp);
ed->description = mlstr_fread(fp);
SLIST_ADD(ED_DATA, *edp, ed);
}
void ed_fwrite(FILE *fp, ED_DATA *ed)
{
fprintf(fp, "E\n%s~\n", fix_string(ed->keyword));
mlstr_fwrite(fp, NULL, ed->description);
}
AFFECT_DATA *aff_new(void)
{
return calloc(1, sizeof(AFFECT_DATA));
}
AFFECT_DATA *aff_dup(const AFFECT_DATA *paf)
{
AFFECT_DATA *naf = aff_new();
naf->where = paf->where;
naf->type = paf->type;
naf->level = paf->level;
naf->duration = paf->duration;
naf->location = paf->location;
naf->modifier = paf->modifier;
naf->bitvector = paf->bitvector;
return naf;
}
void aff_free(AFFECT_DATA *af)
{
free(af);
}
OBJ_DATA *free_obj_list;
OBJ_DATA *new_obj(void)
{
OBJ_DATA *obj;
if (free_obj_list) {
obj = free_obj_list;
free_obj_list = free_obj_list->next;
memset(obj, '\0', sizeof(*obj));
}
else
obj = calloc(1, sizeof(*obj));
return obj;
}
void free_obj(OBJ_DATA *obj)
{
AFFECT_DATA *paf, *paf_next;
ED_DATA *ed, *ed_next;
KEY_DATA *key, *key_next;
if (!obj)
return;
for (paf = obj->affected; paf; paf = paf_next)
{
paf_next = paf->next;
aff_free(paf);
}
obj->affected = NULL;
for (ed = obj->ed; ed != NULL; ed = ed_next )
{
ed_next = ed->next;
ed_free(ed);
}
obj->ed = NULL;
if (obj->keys)
{
// loop thru the keys and free the allocated memory
for ( key = obj->keys; key != NULL; key = key_next)
{
key_next = key->next;
free_key(key);
}
}
free_string(obj->name);
obj->name = NULL;
mlstr_free(obj->description);
obj->description = NULL;
mlstr_free(obj->short_descr);
obj->short_descr = NULL;
free_string(obj->owner);
obj->owner = NULL;
free_string(obj->material);
obj->material = NULL;
obj->next = free_obj_list;
free_obj_list = obj;
}
CHAR_DATA *free_char_list;
CHAR_DATA *new_char (void)
{
CHAR_DATA *ch;
int i;
if (free_char_list) {
ch = free_char_list;
free_char_list = free_char_list->next;
memset(ch, '\0', sizeof(*ch));
}
else
ch = calloc(1, sizeof(*ch));
ch->remembered_rooms.nsize = sizeof(memento_t);
ch->remembered_rooms.nstep = 4;
ch->remembered_objects.nsize = sizeof(memento_t);
ch->remembered_objects.nstep = 4;
ch->remembered_mobs.nsize = sizeof(memento_t);
ch->remembered_mobs.nstep = 4;
ch->remembered_people.nsize = sizeof(memento_t);
ch->remembered_people.nstep = 4;
RESET_FIGHT_TIME(ch);
ch->last_death_time = -1;
ch->prefix = str_empty;
ch->lines = PAGELEN;
ch->logon = current_time;
ch->hit = 20;
ch->max_hit = 20;
ch->mana = 100;
ch->max_mana = 100;
ch->move = 100;
ch->max_move = 100;
ch->psp = 10;
ch->position = POS_STANDING;
for (i = 0; i < 4; i++)
ch->armor[i] = 100;
for (i = 0; i < MAX_STATS; i++)
ch->perm_stat[i] = 13;
for (i = 0; i < MAX_DAM; i++)
ch->resists[i] = 0;
ch->immunes = 0;
free_contacts(ch);
ch->doppel = ch;
return ch;
}
extern int mobile_count;
void free_char(CHAR_DATA *ch)
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
if (!ch)
return;
if (IS_NPC(ch))
mobile_count--;
for (obj = ch->carrying; obj; obj = obj_next) {
obj_next = obj->next_content;
extract_obj_nocount(obj);
}
for (paf = ch->affected; paf; paf = paf_next) {
paf_next = paf->next;
affect_remove(ch,paf);
}
ch->affected = NULL;
nuke_slaves (ch);
free_string(ch->name);
ch->name = NULL;
mlstr_free(ch->short_descr);
ch->short_descr = NULL;
mlstr_free(ch->long_descr);
ch->long_descr = NULL;
mlstr_free(ch->description);
ch->description = NULL;
mlstr_free(ch->listen_data);
ch->listen_data = NULL;
free_string(ch->prompt);
ch->prompt = NULL;
free_string(ch->prefix);
ch->prefix = NULL;
free_string(ch->material);
ch->material = NULL;
free_string(ch->in_mind);
ch->in_mind = NULL;
#ifdef IMC
imc_freechardata(ch);
#endif
#ifdef I3
free_i3chardata(ch);
#endif
free_pcdata(ch->pcdata);
ch->pcdata = NULL;
free_contacts(ch);
ch->doppel = NULL;
varr_free(&ch->remembered_rooms);
varr_free(&ch->remembered_objects);
varr_free(&ch->remembered_mobs);
varr_free(&ch->remembered_people);
ch->next = free_char_list;
free_char_list = ch;
if (ch->in_room != NULL)
{
// fuck this, it wouldn't help
//bug("BINGO! free_char: ch->in_room != NULL (%d)", ch->in_room->vnum);
}
}
CHAR_EXPLORED_DATA * new_char_explored_data(void)
{
CHAR_EXPLORED_DATA *explored_data;
explored_data = calloc(1, sizeof(*explored_data));
explored_data->name = str_empty;
return explored_data;
}
void free_char_explored_data(CHAR_EXPLORED_DATA *explored_data)
{
CHAR_EXPLORED_DATA *curr_area;
CHAR_EXPLORED_DATA *next_area;
if (!explored_data)
return;
for (curr_area = explored_data; curr_area;)
{
next_area = curr_area->next;
free_string(curr_area->name);
free(curr_area);
curr_area = next_area;
}
}
PC_DATA * new_pcdata(void)
{
PC_DATA * pcdata;
int i;
pcdata = calloc(1, sizeof(*pcdata));
pcdata->buffer = buf_new(-1);
pcdata->learned.nsize = sizeof(pcskill_t);
pcdata->learned.nstep = 8;
pcdata->pwd = str_empty;
pcdata->bamfin = str_empty;
pcdata->bamfout = str_empty;
pcdata->title = str_empty;
pcdata->pretitle = str_empty;
pcdata->twitlist = str_empty;
pcdata->linked_list = str_empty;
pcdata->granted = str_empty;
pcdata->host = str_empty;
pcdata->last_login = str_empty;
pcdata->marryed = str_empty;
pcdata->proposal = str_empty;
pcdata->prog_vars = str_empty;
pcdata->last_divorce = -1;
pcdata->last_marry = -1;
for (i = 0; i < 6; ++i)
pcdata->rusnames[i] = NULL;
return pcdata;
}
void free_pcdata(PC_DATA *pcdata)
{
int alias;
if (!pcdata)
return;
varr_free(&pcdata->learned);
free_string(pcdata->pwd);
free_string(pcdata->bamfin);
free_string(pcdata->bamfout);
free_string(pcdata->title);
free_string(pcdata->pretitle);
free_string(pcdata->twitlist);
free_string(pcdata->linked_list);
free_string(pcdata->granted);
free_string(pcdata->host);
free_string(pcdata->last_login);
free_string(pcdata->marryed);
free_string(pcdata->proposal);
free_string(pcdata->prog_vars);
buf_free(pcdata->buffer);
/* in this function ALL of the explored areas are being released */
free_char_explored_data(pcdata->explored_areas);
for (alias = 0; alias < MAX_ALIAS; alias++) {
free_string(pcdata->alias[alias]);
free_string(pcdata->alias_sub[alias]);
}
free(pcdata);
}
/* stuff for setting ids */
long last_pc_id;
long last_mob_id;
long last_obj_id;
long get_pc_id(void)
{
return last_pc_id = (current_time <= last_pc_id) ?
last_pc_id + 1 : current_time;
}
long get_mob_id(void)
{
last_mob_id++;
return last_mob_id;
}
long get_obj_id(void)
{
last_obj_id++;
return last_obj_id;
}
MPTRIG *mptrig_new(int type, const char *phrase, int vnum)
{
const char *p;
MPTRIG *mptrig;
mptrig = calloc(1, sizeof(*mptrig));
mptrig->type = type;
mptrig->vnum = vnum;
mptrig->phrase = str_dup(phrase);
for (p = mptrig->phrase; *p; p++)
if (ISUPPER(*p)) {
SET_BIT(mptrig->flags, TRIG_CASEDEP);
break;
}
if ((type == TRIG_ACT || type == TRIG_SPEECH) && phrase[0] == '*') {
int errcode;
int cflags = REG_EXTENDED | REG_NOSUB;
SET_BIT(mptrig->flags, TRIG_REGEXP);
if (!IS_SET(mptrig->flags, TRIG_CASEDEP))
cflags |= REG_ICASE;
mptrig->extra = malloc(sizeof(regex_t));
errcode = regcomp(mptrig->extra, phrase+1, cflags);
if (errcode) {
char buf[MAX_STRING_LENGTH];
regerror(errcode, mptrig->extra, buf, sizeof(buf));
log_printf("bad MOB trigger for vnum %d (phrase '%s'): %s",
vnum, phrase, buf);
}
}
return mptrig;
}
void mptrig_add(MOB_INDEX_DATA *mob, MPTRIG *mptrig)
{
SET_BIT(mob->mptrig_types, mptrig->type);
SLIST_ADD(MPTRIG, mob->mptrig_list, mptrig);
}
void mptrig_fix(MOB_INDEX_DATA *mob)
{
MPTRIG *mptrig;
for (mptrig = mob->mptrig_list; mptrig; mptrig = mptrig->next)
SET_BIT(mob->mptrig_types, mptrig->type);
}
void mptrig_free(MPTRIG *mp)
{
if (!mp)
return;
if (IS_SET(mp->flags, TRIG_REGEXP)) {
regfree(mp->extra);
free(mp->extra);
}
free_string(mp->phrase);
free(mp);
}
/*-------------------------- OBJ Sections -----------------*/
void optrig_add(OBJ_INDEX_DATA *obj, MPTRIG *optrig)
{
SET_BIT(obj->oprog_flags, optrig->type);
SLIST_ADD(MPTRIG, obj->oprogs, optrig);
}
MPTRIG *optrig_new(int type, const char *phrase, int vnum)
{
const char *p;
MPTRIG *optrig;
optrig = calloc(1, sizeof(*optrig));
optrig->type = type;
optrig->vnum = vnum;
optrig->phrase = str_dup(phrase);
for (p = optrig->phrase; *p; p++)
if (ISUPPER(*p))
{
SET_BIT(optrig->flags, TRIG_CASEDEP);
break;
}
if ((type == TRIG_ACT || type == TRIG_SPEECH) && phrase[0] == '*')
{
int errcode;
int cflags = REG_EXTENDED | REG_NOSUB;
SET_BIT(optrig->flags, TRIG_REGEXP);
if (!IS_SET(optrig->flags, TRIG_CASEDEP))
cflags |= REG_ICASE;
optrig->extra = malloc(sizeof(regex_t));
errcode = regcomp(optrig->extra, phrase+1, cflags);
if (errcode)
{
char buf[MAX_STRING_LENGTH];
regerror(errcode, optrig->extra, buf, sizeof(buf));
log_printf("bad OBJ trigger for vnum %d (phrase '%s'): %s", vnum, phrase, buf);
}
}
return optrig;
}
void optrig_fix(OBJ_INDEX_DATA *obj)
{
MPTRIG *optrig;
for (optrig = obj->oprogs; optrig; optrig = optrig->next)
SET_BIT(obj->oprog_flags, optrig->type);
}
void optrig_free(MPTRIG *op)
{
if (!op)
return;
if (IS_SET(op->flags, TRIG_REGEXP))
{
regfree(op->extra);
free(op->extra);
}
free_string(op->phrase);
free(op);
}
/*-------------------------- OBJ Sections -----------------*/
void rptrig_add(ROOM_INDEX_DATA *room, MPTRIG *rptrig)
{
SET_BIT(room->rprog_flags, rptrig->type);
SLIST_ADD(MPTRIG, room->rprogs, rptrig);
}
MPTRIG *rptrig_new(int type, const char *phrase, int vnum)
{
const char *p;
MPTRIG *rptrig;
rptrig = calloc(1, sizeof(*rptrig));
rptrig->type = type;
rptrig->vnum = vnum;
rptrig->phrase = str_dup(phrase);
for (p = rptrig->phrase; *p; p++)
if (ISUPPER(*p))
{
SET_BIT(rptrig->flags, TRIG_CASEDEP);
break;
}
if ((type == TRIG_ACT || type == TRIG_SPEECH) && phrase[0] == '*')
{
int errcode;
int cflags = REG_EXTENDED | REG_NOSUB;
SET_BIT(rptrig->flags, TRIG_REGEXP);
if (!IS_SET(rptrig->flags, TRIG_CASEDEP))
cflags |= REG_ICASE;
rptrig->extra = malloc(sizeof(regex_t));
errcode = regcomp(rptrig->extra, phrase+1, cflags);
if (errcode)
{
char buf[MAX_STRING_LENGTH];
regerror(errcode, rptrig->extra, buf, sizeof(buf));
log_printf("bad ROOM trigger for vnum %d (phrase '%s'): %s", vnum, phrase, buf);
}
}
return rptrig;
}
void rptrig_fix(ROOM_INDEX_DATA *room)
{
MPTRIG *rptrig;
for (rptrig = room->rprogs; rptrig; rptrig = rptrig->next)
SET_BIT(room->rprog_flags, rptrig->type);
}
void rptrig_free(MPTRIG *rp)
{
if (!rp)
return;
if (IS_SET(rp->flags, TRIG_REGEXP))
{
regfree(rp->extra);
free(rp->extra);
}
free_string(rp->phrase);
free(rp);
}