/* Crimson2 Mud Server * All source written/copyright Ryan Haksi 1995 * * This source code is proprietary. Use in whole or in part without * explicity permission by the author is strictly prohibited * * Current email address(es): cryogen@infoserve.net * Phone number: (604) 591-5295 * * C4 Script Language written/copyright Cam Lesiuk 1995 * Email: clesiuk@engr.uvic.ca */ /* exit.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "crimson2.h" #include "macro.h" #include "log.h" #include "mem.h" #include "str.h" #include "index.h" #include "extra.h" #include "thing.h" #include "exit.h" #include "world.h" #define EXIT_BLOCK_SIZE 4096 LWORD exitNum = 0; BYTE *dirList[] = { "north", "east", "south", "west", "up", "down", "out", "undefined", "" }; /* the order in which exits will be listed */ LWORD eOrderList[] = { EDIR_WEST, EDIR_NORTH, EDIR_SOUTH, EDIR_EAST, EDIR_UP, EDIR_DOWN, EDIR_OUT, EDIR_UNDEFINED, EDIR_MAX }; BYTE *eFlagList[] = { "ISDOOR", "PICKPROOF", "LOCKED", "CLOSED", "HIDDEN", "ELECTRONIC", "NOPHASE", "" }; BYTE reverseDirList[] = { EDIR_SOUTH, EDIR_WEST, EDIR_NORTH, EDIR_EAST, EDIR_DOWN, EDIR_UP, EDIR_UNDEFINED, EDIR_UNDEFINED }; EXIT *ExitAlloc(EXIT *eNext, BYTE eDir, STR *eKey, STR *eDesc, FLAG eFlag, WORD eKeyObj, THING *eWorld) { EXIT *exit; MEMALLOC(exit, EXIT, EXIT_BLOCK_SIZE); exit->eNext = eNext; exit->eDir = eDir; exit->eKey = eKey; exit->eDesc = eDesc; exit->eFlag = eFlag; exit->eKeyObj=eKeyObj; exit->eWorld= eWorld; exitNum++; return exit; } EXIT *ExitCreate(EXIT *eNext, BYTE eDir, BYTE *eKey, BYTE *eDesc, FLAG eFlag, WORD eKeyObj, THING *eWorld) { STR *sKey; STR *sDesc; /* Check to see if an exit in this direction already exists */ if (ExitDir(eNext,eDir)) return NULL; sKey = STRCREATE(eKey); sDesc = STRCREATE(eDesc); return ExitAlloc(eNext, eDir, sKey, sDesc, eFlag, eKeyObj, eWorld); } EXIT *ExitFind(EXIT *eList, BYTE *eKey) { EXIT *exit; LWORD i; if (!eKey) return NULL; exit = NULL; i = TYPEFIND(eKey, dirList); if (i != -1) { for (exit = eList; exit && (exit->eDir != i); exit = exit->eNext); } /* if we havent found a matching dir then search on keyword */ if (exit==NULL) { for (exit = eList; exit && !StrIsKey(eKey, exit->eKey); exit = exit->eNext); } return exit; /* exit will be either the found exit or Null */ } EXIT *ExitDir(EXIT *eList, BYTE eDir) { EXIT *exit; if (eDir == EDIR_UNDEFINED) return NULL; for (exit = eList; exit && (exit->eDir != eDir); exit = exit->eNext); return exit; /* exit will be either the found exit or Null */ } /* Find the exit that points back to us */ EXIT *ExitReverse(THING *world, EXIT *exit) { EXIT *eList; EXIT *reverse = NULL; if (!exit) return NULL; if (!(exit->eWorld)) return NULL; /* look for the obvious choice - a return path back along the opposite direction */ if (exit->eDir!=EDIR_UNDEFINED) { eList = Wld(exit->eWorld)->wExit; reverse = ExitDir(eList, reverseDirList[exit->eDir]); if (reverse && reverse->eWorld == world) return reverse; } /* look for a return exit with a corner in it */ for (reverse = eList; reverse && (reverse->eWorld != world); reverse = reverse->eNext); return reverse; /* exit will be either the found exit or Null */ } /* this esoteric piece of code determines if there is a bend in a pair of exits ie if you leave north from one room and come in from the west into the destination we could reasonably assume that there is a corner in the way This is important since weapons cannot fire around corners! */ LWORD ExitIsCorner(EXIT *exit, EXIT *reverse) { if (exit && reverse) { if (exit->eDir == EDIR_UNDEFINED || reverse->eDir == EDIR_UNDEFINED) return TRUE; if (exit->eDir == reverseDirList[reverse->eDir]) return TRUE; } return FALSE; } EXIT *ExitFree(EXIT *eList, EXIT *exit) { EXIT *i; EXIT *eFree; if (!exit) return eList; exitNum -= 1; while (IndexFind(&eventThingIndex, exit, NULL)) IndexDelete(&eventThingIndex, exit, NULL); if (eList == exit) { eFree = eList; eList = eList->eNext; STRFREE(eFree->eKey); STRFREE(eFree->eDesc); MEMFREE(eFree, EXIT); return eList; } for (i = eList; i && i->eNext != exit; i = i->eNext); if (i) { /* found it */ eFree = i->eNext; i->eNext = eFree->eNext; STRFREE(eFree->eKey); STRFREE(eFree->eDesc); MEMFREE(eFree, EXIT); } else { eFree = exit; STRFREE(eFree->eKey); STRFREE(eFree->eDesc); MEMFREE(eFree, EXIT); } return eList; } BYTE *ExitGetName(EXIT *exit, BYTE *buf) { if (exit->eDir != EDIR_UNDEFINED) { strcpy(buf, dirList[exit->eDir]); } else { StrOneWord(exit->eKey->sText, buf); } return buf; }