/* ******************************************************************** *
* FILE : assemblies.c Copyright (C) 1999 Geoff Davis
*
* USAGE: Implementation for assembly engine. *
* -------------------------------------------------------------------- *
* 1999 MAY 07 gdavis/azrael@laker.net Initial implementation. *
* ******************************************************************** */
#define __ASSEMBLIES_C__
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "assemblies.h"
#include "comm.h"
#include "constants.h"
#include "db.h"
#include "handler.h"
#include "interpreter.h"
/* Local global variables. */
long g_lNumAssemblies = 0;
ASSEMBLY *g_pAssemblyTable = NULL;
/* External global variables. */
extern struct obj_data *obj_proto;
extern struct room_data *world;
void assemblyBootAssemblies( void )
{
char szLine[ MAX_STRING_LENGTH ] = { '\0' };
char szTag[ MAX_STRING_LENGTH ] = { '\0' };
char szType[ MAX_STRING_LENGTH ] = { '\0' };
int iExtract = 0;
int iInRoom = 0;
int iType = 0;
long lLineCount = 0;
long lPartVnum = NOTHING;
long lVnum = NOTHING;
FILE *pFile = NULL;
if( (pFile = fopen( ASSEMBLIES_FILE, "rt" )) == NULL )
{
log( "SYSERR: assemblyBootAssemblies(): Couldn't open file '%s' for "
"reading.", ASSEMBLIES_FILE );
return;
}
while( !feof( pFile ) )
{
lLineCount += get_line( pFile, szLine );
half_chop( szLine, szTag, szLine );
if( *szTag == '\0' )
continue;
if( str_cmp( szTag, "Component" ) == 0 )
{
if( sscanf( szLine, "#%ld %d %d", &lPartVnum, &iExtract, &iInRoom ) != 3
)
{
log( "SYSERR: bootAssemblies(): Invalid format in file %s, line %ld: "
"szTag=%s, szLine=%s.", ASSEMBLIES_FILE, lLineCount, szTag, szLine );
}
else if( !assemblyAddComponent( lVnum, lPartVnum, iExtract, iInRoom ) )
{
log( "SYSERR: bootAssemblies(): Could not add component #%ld to "
"assembly #%ld.", lPartVnum, lVnum );
}
}
else if( str_cmp( szTag, "Vnum" ) == 0 )
{
if( sscanf( szLine, "#%ld %s", &lVnum, szType ) != 2 )
{
log( "SYSERR: bootAssemblies(): Invalid format in file %s, "
"line %ld.", ASSEMBLIES_FILE, lLineCount );
lVnum = NOTHING;
}
else if( (iType = search_block( szType, AssemblyTypes, TRUE )) < 0 )
{
log( "SYSERR: bootAssemblies(): Invalid type '%s' for assembly "
"vnum #%ld at line %ld.", szType, lVnum, lLineCount );
lVnum = NOTHING;
}
else if( !assemblyCreate( lVnum, iType ) )
{
log( "SYSERR: bootAssemblies(): Could not create assembly for vnum "
"#%ld, type %s.", lVnum, szType );
lVnum = NOTHING;
}
}
else
{
log( "SYSERR: Invalid tag '%s' in file %s, line #%ld.", szTag,
ASSEMBLIES_FILE, lLineCount );
}
*szLine = '\0';
*szTag = '\0';
}
fclose( pFile );
}
void assemblySaveAssemblies( void )
{
char szType[ MAX_STRING_LENGTH ] = { '\0' };
long i = 0;
long j = 0;
ASSEMBLY *pAssembly = NULL;
FILE *pFile = NULL;
if( (pFile = fopen( ASSEMBLIES_FILE, "wt" )) == NULL )
{
log( "SYSERR: assemblySaveAssemblies(): Couldn't open file '%s' for "
"writing.", ASSEMBLIES_FILE );
return;
}
for( i = 0; i < g_lNumAssemblies; i++)
{
pAssembly = (g_pAssemblyTable + i);
sprinttype(pAssembly->uchAssemblyType,AssemblyTypes,szType, sizeof(szType));
fprintf( pFile, "Vnum #%ld %s\n", pAssembly->lVnum, szType );
for( j = 0; j < pAssembly->lNumComponents; j++ )
{
fprintf( pFile, "Component #%ld %d %d\n",
pAssembly->pComponents[ j ].lVnum,
(pAssembly->pComponents[ j ].bExtract ? 1 : 0),
(pAssembly->pComponents[ j ].bInRoom ? 1 : 0) );
}
if( i < g_lNumAssemblies - 1 )
fprintf( pFile, "\n" );
}
fclose( pFile );
}
void assemblyListToChar( struct char_data *pCharacter )
{
char szBuffer[ MAX_STRING_LENGTH ] = { '\0' };
char szAssmType[ MAX_INPUT_LENGTH ] = { '\0' };
long i = 0; // Outer iterator.
long j = 0; // Inner iterator.
long lRnum = 0; // Object rnum for obj_proto indexing.
if( pCharacter == NULL )
{
log( "SYSERR: assemblyListAssembliesToChar(): NULL 'pCharacter'." );
return;
}
else if( g_pAssemblyTable == NULL )
{
send_to_char(pCharacter, "No assemblies exist.\r\n");
return;
}
/* Send out a "header" of sorts. */
send_to_char(pCharacter, "The following assemblies exists:\r\n");
for( i = 0; i < g_lNumAssemblies; i++ )
{
if( (lRnum = real_object( g_pAssemblyTable[ i ].lVnum )) < 0 )
{
send_to_char(pCharacter, "[-----] ***RESERVED***\r\n");
log( "SYSERR: assemblyListToChar(): Invalid vnum #%ld in assembly table.", g_pAssemblyTable[i].lVnum);
}
else
{
sprinttype(g_pAssemblyTable[ i ].uchAssemblyType, AssemblyTypes, szAssmType, sizeof(szAssmType));
sprintf( szBuffer, "[%5ld] %s (%s)\r\n", g_pAssemblyTable[ i ].lVnum,
obj_proto[ lRnum ].short_description, szAssmType );
send_to_char(pCharacter, szBuffer);
for( j = 0; j < g_pAssemblyTable[ i ].lNumComponents; j++ )
{
if( (lRnum = real_object( g_pAssemblyTable[ i ].pComponents[ j ].lVnum )) < 0 )
{
send_to_char(pCharacter, " -----: ***RESERVED***\r\n");
log( "SYSERR: assemblyListToChar(): Invalid component vnum #%ld in assembly for vnum #%ld.",
g_pAssemblyTable[ i ].pComponents[ j ].lVnum, g_pAssemblyTable[ i ].lVnum );
}
else
{
sprintf( szBuffer, " %5ld: %-20.20s Extract=%-3.3s InRoom=%-3.3s\r\n",+ g_pAssemblyTable[ i ].pComponents[ j ].lVnum,
obj_proto[ lRnum ].short_description,
(g_pAssemblyTable[ i ].pComponents[ j ].bExtract ? "Yes" : "No"),
(g_pAssemblyTable[ i ].pComponents[ j ].bInRoom ? "Yes" : "No") );
send_to_char(pCharacter, szBuffer);
}
}
}
}
}
bool assemblyAddComponent( long lVnum, long lComponentVnum, bool bExtract, bool bInRoom )
{
ASSEMBLY *pAssembly = NULL;
COMPONENT *pNewComponents = NULL;
if( (pAssembly = assemblyGetAssemblyPtr( lVnum )) == NULL )
{
log( "SYSERR: assemblyAddComponent(): Invalid 'lVnum' #%ld.", lVnum );
return (FALSE);
}
else if( real_object( lComponentVnum ) < 0 )
{
log( "SYSERR: assemblyAddComponent(): Invalid 'lComponentVnum' #%ld.",
lComponentVnum );
return (FALSE);
}
else if( assemblyHasComponent( lVnum, lComponentVnum ) )
{
log( "SYSERR: assemblyAddComponent(): Assembly for vnum #%ld already "
"has component vnum #%ld.", lVnum, lComponentVnum );
return (FALSE);
}
/* Create a new component table with room for one more entry. */
CREATE( pNewComponents, COMPONENT, pAssembly->lNumComponents + 1 );
if( pAssembly->pComponents != NULL )
{
/* Copy the old table over to the new. */
memmove( pNewComponents, pAssembly->pComponents, pAssembly->lNumComponents
* sizeof( COMPONENT ) );
free( pAssembly->pComponents );
}
/*
* Assign the new component table and setup the new component entry. Then
* add increment the number of components.
*/
pAssembly->pComponents = pNewComponents;
pAssembly->pComponents[ pAssembly->lNumComponents ].lVnum = lComponentVnum;
pAssembly->pComponents[ pAssembly->lNumComponents ].bExtract = bExtract;
pAssembly->pComponents[ pAssembly->lNumComponents ].bInRoom = bInRoom;
pAssembly->lNumComponents += 1;
return (TRUE);
}
bool assemblyCheckComponents( long lVnum, struct char_data *pCharacter )
{
bool bOk = TRUE;
long i = 0;
long lRnum = 0;
struct obj_data **ppComponentObjects = NULL;
ASSEMBLY *pAssembly = NULL;
if( pCharacter == NULL )
{
log( "SYSERR: NULL assemblyCheckComponents(): 'pCharacter'." );
return (FALSE);
}
else if( (pAssembly = assemblyGetAssemblyPtr( lVnum )) == NULL )
{
log( "SYSERR: NULL assemblyCheckComponents(): Invalid 'lVnum' #%ld.", lVnum );
return (FALSE);
}
if( pAssembly->pComponents == NULL )
return (FALSE);
else if( pAssembly->lNumComponents <= 0 )
return (FALSE);
CREATE( ppComponentObjects, struct obj_data*, pAssembly->lNumComponents );
for( i = 0; i < pAssembly->lNumComponents && bOk; i++ )
{
if( (lRnum = real_object( pAssembly->pComponents[ i ].lVnum )) < 0 )
bOk = FALSE;
else
{
if( pAssembly->pComponents[ i ].bInRoom )
{
if( (ppComponentObjects[ i ] = get_obj_in_list_num( lRnum,
world[ IN_ROOM( pCharacter ) ].contents )) == NULL )
bOk = FALSE;
else
obj_from_room( ppComponentObjects[ i ] );
}
else
{
if( (ppComponentObjects[ i ] = get_obj_in_list_num( lRnum,
pCharacter->carrying )) == NULL )
bOk = FALSE;
else
obj_from_char( ppComponentObjects[ i ] );
}
}
}
for( i = 0; i < pAssembly->lNumComponents; i++ )
{
if( ppComponentObjects[ i ] == NULL )
continue;
if( pAssembly->pComponents[ i ].bExtract && bOk )
extract_obj( ppComponentObjects[ i ] );
else if( pAssembly->pComponents[ i ].bInRoom )
obj_to_room( ppComponentObjects[ i ], IN_ROOM( pCharacter ) );
else
obj_to_char( ppComponentObjects[ i ], pCharacter );
}
free( ppComponentObjects );
return (bOk);
}
bool assemblyCreate( long lVnum, int iAssembledType )
{
long lBottom = 0;
long lMiddle = 0;
long lTop = 0;
ASSEMBLY *pNewAssemblyTable = NULL;
if( lVnum < 0 )
return (FALSE);
else if( iAssembledType < 0 || iAssembledType >= MAX_ASSM )
return (FALSE);
if( g_pAssemblyTable == NULL )
{
CREATE( g_pAssemblyTable, ASSEMBLY, 1 );
g_lNumAssemblies = 1;
}
else
{
lTop = g_lNumAssemblies - 1;
for( ;; )
{
lMiddle = (lBottom + lTop) / 2;
if( g_pAssemblyTable[ lMiddle ].lVnum == lVnum )
return (FALSE);
else if( lBottom >= lTop )
break;
else if( g_pAssemblyTable[ lMiddle ].lVnum > lVnum )
lTop = lMiddle - 1;
else
lBottom = lMiddle + 1;
}
if( g_pAssemblyTable[ lMiddle ].lVnum <= lVnum )
lMiddle += 1;
CREATE( pNewAssemblyTable, ASSEMBLY, g_lNumAssemblies + 1 );
if( lMiddle > 0 )
memmove( pNewAssemblyTable, g_pAssemblyTable, lMiddle * sizeof( ASSEMBLY
) );
if( lMiddle <= g_lNumAssemblies - 1 )
memmove( pNewAssemblyTable + lMiddle + 1, g_pAssemblyTable + lMiddle, (g_lNumAssemblies - lMiddle) * sizeof( ASSEMBLY ) );
free( g_pAssemblyTable );
g_pAssemblyTable = pNewAssemblyTable;
g_lNumAssemblies += 1;
}
g_pAssemblyTable[ lMiddle ].lNumComponents = 0;
g_pAssemblyTable[ lMiddle ].lVnum = lVnum;
g_pAssemblyTable[ lMiddle ].pComponents = NULL;
g_pAssemblyTable[ lMiddle ].uchAssemblyType = (unsigned char) iAssembledType;
return (TRUE);
}
bool assemblyDestroy( long lVnum )
{
long lIndex = 0;
ASSEMBLY *pNewAssemblyTable = NULL;
/* Find the real number of the assembled vnum. */
if( g_pAssemblyTable == NULL || (lIndex = assemblyGetAssemblyIndex( lVnum ))
< 0 )
{
log( "SYSERR: assemblyDestroy(): Invalid 'lVnum' #%ld.", lVnum );
return (FALSE);
}
/* Deallocate component array. */
if( g_pAssemblyTable[ lIndex ].pComponents != NULL )
free( g_pAssemblyTable[ lIndex ].pComponents );
if( g_lNumAssemblies > 1 )
{
/* Create a new table, the same size as the old one less one item. */
CREATE( pNewAssemblyTable, ASSEMBLY, g_lNumAssemblies - 1 );
/* Copy all assemblies before the one removed into the new table. */
if( lIndex > 0 )
memmove( pNewAssemblyTable, g_pAssemblyTable, lIndex * sizeof( ASSEMBLY ) );
/* Copy all assemblies after the one removed into the new table. */
if( lIndex < g_lNumAssemblies - 1 )
{
memmove( pNewAssemblyTable + lIndex, g_pAssemblyTable + lIndex + 1, (g_lNumAssemblies - lIndex - 1) *
sizeof( ASSEMBLY ) );
}
}
/* Deallocate the old table. */
free( g_pAssemblyTable );
/* Decrement the assembly count and assign the new table. */
g_lNumAssemblies -= 1;
g_pAssemblyTable = pNewAssemblyTable;
return (TRUE);
}
bool assemblyHasComponent( long lVnum, long lComponentVnum )
{
ASSEMBLY *pAssembly = NULL;
if( (pAssembly = assemblyGetAssemblyPtr( lVnum )) == NULL )
{
log( "SYSERR: assemblyHasComponent(): Invalid 'lVnum' #%ld.", lVnum );
return (FALSE);
}
return (assemblyGetComponentIndex( pAssembly, lComponentVnum ) >= 0);
}
bool assemblyRemoveComponent( long lVnum, long lComponentVnum )
{
long lIndex = 0;
ASSEMBLY *pAssembly = NULL;
COMPONENT *pNewComponents = NULL;
if( (pAssembly = assemblyGetAssemblyPtr( lVnum )) == NULL )
{
log( "SYSERR: assemblyRemoveComponent(): Invalid 'lVnum' #%ld.", lVnum );
return (FALSE);
}
else if( (lIndex = assemblyGetComponentIndex( pAssembly, lComponentVnum )) <
0 )
{
log( "SYSERR: assemblyRemoveComponent(): Vnum #%ld is not a "
"component of assembled vnum #%ld.", lComponentVnum, lVnum );
return (FALSE);
}
if( pAssembly->pComponents != NULL && pAssembly->lNumComponents > 1 )
{
CREATE( pNewComponents, COMPONENT, pAssembly->lNumComponents - 1 );
if( lIndex > 0 )
memmove( pNewComponents, pAssembly->pComponents, lIndex * sizeof( COMPONENT ) );
if( lIndex < pAssembly->lNumComponents - 1 )
{
memmove( pNewComponents + lIndex, pAssembly->pComponents + lIndex + 1,
(pAssembly->lNumComponents - lIndex - 1) * sizeof( COMPONENT ) );
}
}
free( pAssembly->pComponents );
pAssembly->pComponents = pNewComponents;
pAssembly->lNumComponents -= 1;
return (TRUE);
}
int assemblyGetType( long lVnum )
{
ASSEMBLY *pAssembly = NULL;
if( (pAssembly = assemblyGetAssemblyPtr( lVnum )) == NULL )
{
log( "SYSERR: assemblyGetType(): Invalid 'lVnum' #%ld.", lVnum );
return (-1);
}
return ((int) pAssembly->uchAssemblyType);
}
long assemblyCountComponents( long lVnum )
{
ASSEMBLY *pAssembly = NULL;
if( (pAssembly = assemblyGetAssemblyPtr( lVnum )) == NULL )
{
log( "SYSERR: assemblyCountComponents(): Invalid 'lVnum' #%ld.", lVnum );
return (0);
}
return (pAssembly->lNumComponents);
}
long assemblyFindAssembly( const char *pszAssemblyName )
{
long i = 0;
long lRnum = NOTHING;
if( g_pAssemblyTable == NULL )
return (-1);
else if( pszAssemblyName == NULL || *pszAssemblyName == '\0' )
return (-1);
for( i = 0; i < g_lNumAssemblies; i++ )
{
if( (lRnum = real_object( g_pAssemblyTable[ i ].lVnum )) < 0 )
log( "SYSERR: assemblyFindAssembly(): Invalid vnum #%ld in assembly table.", g_pAssemblyTable[i].lVnum );
else if( isname( pszAssemblyName, obj_proto[ lRnum ].name ) )
return (g_pAssemblyTable[ i ].lVnum);
}
return (-1);
}
long assemblyGetAssemblyIndex( long lVnum )
{
long lBottom = 0;
long lMiddle = 0;
long lTop = 0;
lTop = g_lNumAssemblies - 1;
for( ;; )
{
lMiddle = (lBottom + lTop) / 2;
if( g_pAssemblyTable[ lMiddle ].lVnum == lVnum )
return (lMiddle);
else if( lBottom >= lTop )
return (-1);
else if( g_pAssemblyTable[ lMiddle ].lVnum > lVnum )
lTop = lMiddle - 1;
else
lBottom = lMiddle + 1;
}
}
long assemblyGetComponentIndex( ASSEMBLY *pAssembly, long lComponentVnum )
{
long i = 0;
if( pAssembly == NULL )
return (-1);
for( i = 0; i < pAssembly->lNumComponents; i++ )
{
if( pAssembly->pComponents[ i ].lVnum == lComponentVnum )
return (i);
}
return (-1);
}
ASSEMBLY* assemblyGetAssemblyPtr( long lVnum )
{
long lIndex = 0;
if( g_pAssemblyTable == NULL )
return (NULL);
if( (lIndex = assemblyGetAssemblyIndex( lVnum )) >= 0 )
return (g_pAssemblyTable + lIndex);
return (NULL);
}
#undef __ASSEMBLIES_C__