diff --git a/src/lists.c b/src/lists.c new file mode 100644 index 0000000..8ebfbe8 --- /dev/null +++ b/src/lists.c @@ -0,0 +1,321 @@ +/************************************************************************** +* File: lists.c Part of tbaMUD * +* Usage: Loading/saving/editing of Ideas, Bugs and Typos lists * +* * +* All rights reserved. See license for complete information. * +* * +* Written by Joseph Arnusch (Vatiken) for the tbaMUD codebase * +* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * +* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * +**************************************************************************/ + +#include "conf.h" +#include "sysdep.h" +#include "structs.h" +#include "utils.h" +#include "db.h" +#include "dg_event.h" + +/* Global lists */ +struct list_data * global_lists = NULL; + +struct list_data * create_list(void) +{ + struct list_data *pNewList; + static bool first_list = TRUE; + + CREATE(pNewList, struct list_data, 1); + + pNewList->pFirstItem = NULL; + pNewList->pLastItem = NULL; + pNewList->iIterators = 0; + pNewList->iSize = 0; + + /* Add to global lists, primarily for debugging purposes */ + if (first_list == FALSE) { + mudlog(CMP, LVL_GOD, TRUE, "Adding to global list."); + add_to_list(pNewList, global_lists); + } else + first_list = FALSE; + + return (pNewList); +} + +struct item_data * create_item(void) +{ + struct item_data *pNewItem; + + CREATE(pNewItem, struct item_data, 1); + + pNewItem->pNextItem = NULL; + pNewItem->pPrevItem = NULL; + pNewItem->pContent = NULL; + + return (pNewItem); +} + +void free_list(struct list_data * pList) +{ + void * pContent; + + if (pList->iSize) + while ((pContent = simple_list(pList))) + remove_from_list(pContent, pList); + + if (pList->iSize > 0) + mudlog(CMP, LVL_GOD, TRUE, "List being freed while not empty."); + + /* Global List for debugging */ + mudlog(CMP, LVL_GOD, TRUE, "Removing from global list."); + remove_from_list(pList, global_lists); + + free(pList); +} + +void add_to_list(void * pContent, struct list_data * pList) +{ + struct item_data * pNewItem; + struct item_data * pLastItem; + + /* Allocate our memory */ + pNewItem = create_item(); + + /* Place the contents in the item */ + pNewItem->pContent = pContent; + pNewItem->pNextItem = NULL; + + /* If we are the first entry in the list, mark us as such */ + if (pList->pFirstItem == NULL) + pList->pFirstItem = pNewItem; + + /* Grab our last item from the list and attach it to our new item */ + if (pList->pLastItem) { + pLastItem = pList->pLastItem; + pLastItem->pNextItem = pNewItem; + pNewItem->pPrevItem = pLastItem; + } + + /* Make our new item our last item in the list */ + pList->pLastItem = pNewItem; + + pList->iSize++; +} + +void remove_from_list(void * pContent, struct list_data * pList) +{ + struct item_data *pRemovedItem; + + if ((pRemovedItem = find_in_list(pContent, pList)) == NULL) { + mudlog(CMP, LVL_GOD, TRUE, "SYSERR: Attempting to remove contents that don't exist in list."); + return; + } + + if (pRemovedItem == pList->pFirstItem) + pList->pFirstItem = pRemovedItem->pNextItem; + + if (pRemovedItem == pList->pLastItem) + pList->pLastItem = pRemovedItem->pPrevItem; + + if (pRemovedItem->pPrevItem) + pRemovedItem->pPrevItem->pNextItem = pRemovedItem->pNextItem; + + if (pRemovedItem->pNextItem) + pRemovedItem->pNextItem->pPrevItem = pRemovedItem->pPrevItem; + + pList->iSize--; + + if (pList->iSize == 0) { + pList->pFirstItem = NULL; + pList->pLastItem = NULL; + } + + free(pRemovedItem); +} + +/** Merges an iterator with a list + * @post Don't forget to remove the iterator with remove_iterator(). + * */ + +void * merge_iterator(struct iterator_data * pIterator, struct list_data * pList) +{ + void * pContent; + + if (pList == NULL) { + mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Attempting to merge iterator to NULL list."); + pIterator->pList = NULL; + pIterator->pItem = NULL; + return NULL; + } + if (pList->pFirstItem == NULL) { + mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Attempting to merge iterator to empty list."); + pIterator->pList = NULL; + pIterator->pItem = NULL; + return NULL; + } + + pList->iIterators++; + pIterator->pList = pList; + pIterator->pItem = pList->pFirstItem; + + pContent = pIterator->pItem ? pIterator->pItem->pContent : NULL; + + return (pContent); +} + +void remove_iterator(struct iterator_data * pIterator) +{ + if (pIterator->pList == NULL) { + mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Attempting to remove iterator from NULL list."); + return; + } + + pIterator->pList->iIterators--; + pIterator->pList = NULL; + pIterator->pItem = NULL; +} + +/** Spits out an item and cycles down the list + * @return Returns the content of the list + * */ + +void * next_in_list(struct iterator_data * pIterator) +{ + void * pContent; + struct item_data * pTempItem; + + if (pIterator->pList == NULL) { + mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Attempting to get content from iterator with NULL list."); + return NULL; + } + + /* Cycle down the list */ + pTempItem = pIterator->pItem->pNextItem; + pIterator->pItem = pTempItem; + + /* Grab the content */ + pContent = pIterator->pItem ? pIterator->pItem->pContent : NULL; + + return (pContent); +} + +/** Searches through the a list and returns the item block that holds pContent + * @return Returns the actual item block and not the pContent itself, since + * it is assumed you already have the pContent. + * */ + +struct item_data * find_in_list(void * pContent, struct list_data * pList) +{ + struct iterator_data Iterator; + void * pFoundItem; + struct item_data *pItem = NULL; + bool found; + + pFoundItem = merge_iterator(&Iterator, pList); + + for (found = FALSE; pFoundItem != NULL; pFoundItem = next_in_list(&Iterator)) { + if (pFoundItem == pContent) { + found = TRUE; + break; + } + } + + if (found) + pItem = Iterator.pItem; + + remove_iterator(&Iterator); + + if (found) + return (pItem); + else + return NULL; +} + +/** This is the "For Dummies" function, as although it's not as flexible, + * it is even easier applied for list searches then using your own iterators + * and next_in_list() + * @usage Common usage would be as follows: + * + * while ((var = (struct XXX_data *) simple_list(XXX_list))) { + * blah blah.... + * } + * @return Will return the next list content until it hits the end, in which + * will detach itself from the list. + * */ + +void * simple_list(struct list_data * pList) +{ + static struct iterator_data Iterator; + static bool loop = FALSE; + static struct list_data *pLastList = NULL; + void * pContent; + + if (!loop || pLastList != pList) { + if (pLastList != pList) + mudlog(CMP, LVL_GRGOD, TRUE, "SYSERR: simple_list() forced to reset itself."); + + pContent = merge_iterator(&Iterator, pList); + if (pContent != NULL) { + pLastList = pList; + loop = TRUE; + return (pContent); + } else + return NULL; + } + + if ((pContent = next_in_list(&Iterator)) != NULL) + return (pContent); + + remove_iterator(&Iterator); + loop = FALSE; + return NULL; +} + +void * random_from_list(struct list_data * pList) +{ + struct iterator_data Iterator; + void * pFoundItem; + bool found; + int number; + int count = 1; + + if (pList->iSize <= 0) + return NULL; + else + number = rand_number(1, pList->iSize); + + pFoundItem = merge_iterator(&Iterator, pList); + + for (found = FALSE; pFoundItem != NULL; pFoundItem = next_in_list(&Iterator), count++) { + if (count == number) { + found = TRUE; + break; + } + } + + remove_iterator(&Iterator); + + if (found) + return (pFoundItem); + else + return NULL; +} + +struct list_data * randomize_list(struct list_data * pList) +{ + struct list_data * newList; + void * pContent; + + if (pList->iSize == 0) + return NULL; + + newList = create_list(); + + while ((pContent = random_from_list(pList)) != NULL) { + remove_from_list(pContent, pList); + add_to_list(pContent, newList); + } + + free_list(pList); + + return (newList); +} diff --git a/src/lists.h b/src/lists.h new file mode 100644 index 0000000..c7b0a2b --- /dev/null +++ b/src/lists.h @@ -0,0 +1,41 @@ +/* file: list.h + */ + +#ifndef _LISTS_HEADER +#define _LISTS_HEADER + +struct item_data { + struct item_data * pPrevItem; + struct item_data * pNextItem; + void * pContent; +}; + +struct list_data { + struct item_data * pFirstItem; + struct item_data * pLastItem; + int iIterators; + int iSize; +}; + +struct iterator_data { + struct list_data * pList; + struct item_data * pItem; +}; + +/* Externals */ +extern struct list_data * global_lists; +extern struct list_data * ticker_list; + +/* Locals */ +void add_to_list(void * pContent, struct list_data * pList); +void * random_from_list(struct list_data * pList); +struct list_data * randomize_list(struct list_data * pList); +struct list_data * create_list(void); +void * merge_iterator(struct iterator_data * pIterator, struct list_data * pList); +void remove_iterator(struct iterator_data * pIterator); +void * next_in_list(struct iterator_data * pIterator); +void remove_from_list(void * pContent, struct list_data * pList); +struct item_data * find_in_list(void * pContent, struct list_data * pList); +void * simple_list(struct list_data * pList); +void free_list(struct list_data * pList); +#endif diff --git a/src/mud_event.c b/src/mud_event.c new file mode 100644 index 0000000..a29824b --- /dev/null +++ b/src/mud_event.c @@ -0,0 +1,89 @@ + +#include "conf.h" +#include "sysdep.h" +#include "structs.h" +#include "utils.h" +#include "db.h" +#include "dg_event.h" +#include "constants.h" +#include "comm.h" /* For access to the game pulse */ +#include "mud_event.h" + +/* Global List */ +struct list_data * world_events = NULL; + +void init_events(void) +{ + /* Allocate Event List */ + world_events = create_list(); + + /* Attach Our Events */ + attach_mud_event(display_usage, new_mud_event(EVENT_WORLD, NULL, NULL), 10 * PASSES_PER_SEC); +} + +void attach_mud_event(void (*func), struct mud_event_data *pMudEvent, long time) +{ + struct event * pEvent; + struct descriptor_data * d; + struct char_data * ch; + + pEvent = event_create(func, pMudEvent, time); + pEvent->isMudEvent = TRUE; + pMudEvent->pEvent = pEvent; + + switch (pMudEvent->iEvent_Type) { + case EVENT_WORLD: + add_to_list(pEvent, world_events); + break; + case EVENT_DESC: + d = (struct descriptor_data *) pMudEvent->pStruct; + add_to_list(pEvent, d->events); + break; + case EVENT_CHAR: + ch = (struct char_data *) pMudEvent->pStruct; + add_to_list(pEvent, ch->events); + break; + } +} + +struct mud_event_data *new_mud_event(int iEvent_Type, void *pStruct, char *sVariables) +{ + struct mud_event_data *pMudEvent; + char *varString; + + CREATE(pMudEvent, struct mud_event_data, 1); + varString = (sVariables != NULL) ? strdup(sVariables) : NULL; + + pMudEvent->iEvent_Type = iEvent_Type; + pMudEvent->pStruct = pStruct; + pMudEvent->sVariables = varString; + pMudEvent->pEvent = NULL; + + return (pMudEvent); +} + +void free_mud_event(struct mud_event_data *pMudEvent) +{ + struct descriptor_data * d; + struct char_data * ch; + + switch (pMudEvent->iEvent_Type) { + case EVENT_WORLD: + remove_from_list(pMudEvent->pEvent, world_events); + break; + case EVENT_DESC: + d = (struct descriptor_data *) pMudEvent->pStruct; + remove_from_list(pMudEvent->pEvent, d->events); + break; + case EVENT_CHAR: + ch = (struct char_data *) pMudEvent->pStruct; + remove_from_list(pMudEvent->pEvent, ch->events); + break; + } + + if (pMudEvent->sVariables != NULL) + free(pMudEvent->sVariables); + + pMudEvent->pEvent->event_obj = NULL; + free(pMudEvent); +} diff --git a/src/mud_event.h b/src/mud_event.h new file mode 100644 index 0000000..6d71219 --- /dev/null +++ b/src/mud_event.h @@ -0,0 +1,36 @@ +/** +* @file mud_event.h +* +* Part of the core tbaMUD source code distribution, which is a derivative +* of, and continuation of, CircleMUD. +*/ +#ifndef _MUD_EVENT_H_ +#define _MUD_EVENT_H_ + +#include "dg_event.h" + +#define EVENT_WORLD 0 +#define EVENT_DESC 1 +#define EVENT_CHAR 2 + +struct mud_event_data { + struct event * pEvent; + int iEvent_Type; + void * pStruct; + char * sVariables; +}; + +/* Externals */ +extern struct list_data * world_events; + +/* Local Functions */ +void init_events(void); +struct mud_event_data *new_mud_event(int iEvent_Type, void *pStruct, char *sVariables); +void attach_mud_event(void (*func), struct mud_event_data *pMudEvent, long time); +void free_mud_event(struct mud_event_data *pMudEvent); + +/* Events */ +EVENTFUNC(get_protocols); +EVENTFUNC(display_usage); + +#endif /* _MUD_EVENT_H_ */