From: Christopher Feist <Christopher.Feist.feist@nt.com>

Recently I have been working on OLC delete commands since they would
be really handy.

I have come up with working versions of oedit_delete
and medit_delete. redit_delete is still in the works and I dont
think im going to bother with aedit_delete.

The basic premise is that you remove the vnum from the appropriate
hash and then delete all resets which refer to said vnum. This is
of course much easier to say then to do. The tricky part is
getting resets for objects inside other objects. Both of the
delete functions handle these cases.

I specificaly do not free up the index data because doing that
would require me to eliminate every instance of said vnum from
the mud. (because pIndexData still points to this memory location)
This isnt too bad for mobiles but for objects it really
really bites. If someone wants to code it up ill gladly take it
however. :)

I am submitting the two delete functions so that other muds besides
Aeon can test them and maybe force out any small bugs that I havent
caught. I STRONGLY suggest you read and understand what is happening
before you put these in. You will also have to add the hooks in
to call the functions yourself. (That should prevent most copy/paste
implementors from doing dumb things :P)

If you are trying to understand what is happening here I reccomend
uncommenting the debug code in oedit delete as it spews alot less
output then the medit delete code. I admit that neither of these
routines are particularily elegant coding examples however they
do work.

Lastly on Aeon there is a small glitch in medit_delete whereby
the person deleting the mobile somehow has his mount set to
a predictable value sometime after the exit of the function.
(i.e its something in our code not the function)

Unfortunatly I havent been able to figureout how/why/where this happens.
If anyone knows how to break on the change of the value
of a dereferenced pointer in gdb an example would be REALLY REALLY 
appreciated. For those of you who have muds without mount code
(or with mount code) you will have to get rid of that little 
section at the bottom of medit_delete since our mount code
isnt taken from a stock snippet.

Enjoy.

Narbo

Coder @ Aeon
telnet://mud.aeon.org:4000

OEDIT( oedit_delete )
{
     OBJ_INDEX_DATA *pObj;
     OBJ_INDEX_DATA *iObj;
     OBJ_INDEX_DATA *sObj;
     RESET_DATA *pReset = NULL;
     RESET_DATA *prev = NULL;
     ROOM_INDEX_DATA *pRoom = NULL;
     char arg[MIL];
     char buf[MSL];
     int index, count, iHash, i;

     if ( argument[0] == '\0' )
     {
          send_to_char( "Syntax:  oedit delete [vnum]\n\r", ch );
          return FALSE;
     }

     one_argument( argument, arg );

     if( is_number( arg ) )
     {
          index = atoi( arg );
          pObj = get_obj_index( index );
     }
     else
     {
          send_to_char( "That is not a number.\n\r", ch );
          return FALSE;
     }

     SET_BIT( pObj->area->area_flags, AREA_CHANGED );

     /* Remove it from the object list */

     iHash = index % MAX_KEY_HASH;

     /* DEBUG CODE - uncomment this if you have doubts */
     /* printf("\nObject hash for location %d:\n", iHash);
     for ( tObj = obj_index_hash[iHash]; tObj != NULL; tObj = tObj->next )
          printf("name: %s vnum: %d\n", tObj->name, tObj->vnum ); */

     sObj = obj_index_hash[iHash];

     if( sObj->next == NULL ) /* only entry */
          obj_index_hash[iHash] = NULL;
     else if( sObj == pObj ) /* first entry */
          obj_index_hash[iHash] = pObj->next;
     else /* everything else */
     {
          for( iObj = sObj; iObj != NULL; iObj = iObj->next )
          {
               if( iObj ==  pObj )
               {
                    sObj->next = pObj->next;
                    break;
               }
               sObj = iObj;
          }
     }

     /* If you uncomment this you also need to
        find every instance of the object that exists in
        the mud and extract them otherwise each of thier
        pIndexData will be pointing at free memory.
        (Which may or may not contain the actual info)
        As it is all the objects will be removed the reboot/login
        automatically by fread_obj when it cant find the index */

     /* free_string( pObj->name );
     free_string( pObj->short_descr );
     free_string( pObj->description );

     for( pAf = pObj->affected; pAf; pAf = pAf->next )
          free_affect( pAf );

     for( pExtra = pObj->extra_descr; pExtra; pExtra = pExtra->next )
          free_extra_descr( pExtra );

     free( pObj ); */

     /* DEBUG CODE - uncomment this if you have doubts */
     /* printf("\nObject hash for location %d after removal:\n", iHash);
     for ( tObj = obj_index_hash[iHash]; tObj != NULL; tObj = tObj->next )
          printf("name: %s vnum: %d\n", tObj->name, tObj->vnum ); */

     /* DEBUG CODE */
     // printf( "\ntop_vnum_obj before: %d\n", top_vnum_obj );

     if( top_vnum_obj == index )
          for( i = 1; i < index; i++ )
               if( get_obj_index( i ) )
                    top_vnum_obj = i;

     /* DEBUG CODE */
     // printf( "top_vnum_obj after: %d\n", top_vnum_obj );

     top_obj_index--;

     /* Now crush all resets */
     count = 0;
     for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
     {
          for( pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next )
          {
               prev = pRoom->reset_first;
               for( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
               {
                    switch( pReset->command )
                    {
                         case 'O':
                         case 'E':
                         case 'P':
                         case 'G':
                              if( ( pReset->arg1 == index ) ||
                                  ( (  pReset->command == 'P' ) && (
pReset->arg3 == index ) ) )
                              {
                                   // printf("\nprev: %d  prev->next: %d\n",
prev, prev->next );

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d:\n",
pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d 
memloc:%d\n", tReset->command, tReset->arg1, tReset ); */

                                   if( pRoom->reset_first == pReset )
                                   {
                                        pRoom->reset_first = pReset->next;
                                        if( !pRoom->reset_first )
                                             pRoom->reset_last = NULL;
                                   }
                                   else if( pRoom->reset_last == pReset )
                                   {
                                        pRoom->reset_last = prev;
                                        prev->next = NULL;
                                   }
                                   else
                                   {
                                        prev->next = prev->next->next;
                                   }

                                   count++;
                                   SET_BIT( pRoom->area->area_flags,
AREA_CHANGED );

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d after
removal:\n", pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d 
memloc:%d\n", tReset->command, tReset->arg1, tReset ); */

                                   // printf("\nprev: %d  prev->next: %d\n",
prev, prev->next );
                              }
                    }
                    prev = pReset;
               }
          }
     }

     sprintf( buf, "Removed object vnum ^C%d^x and ^C%d^x resets.\n\r", index,
count );
     send_to_char( buf, ch );
     return TRUE;
}


MEDIT( medit_delete )
{
     MOB_INDEX_DATA *pMob;
     MOB_INDEX_DATA *sMob;
     MOB_INDEX_DATA *iMob;
     RESET_DATA *pReset = NULL;
     RESET_DATA *prev= NULL;
     ROOM_INDEX_DATA *pRoom = NULL;
     char arg[MIL];
     char buf[MSL];
     int index, count, iHash, i;
     int dobj[100]; /* I highly doubt one mobile will have 100 unique object
resets */
     bool foundmob = FALSE;
     bool exist = FALSE;
     bool foundobj = FALSE;

     if ( argument[0] == '\0' )
     {
          send_to_char( "Syntax:  medit delete [vnum]\n\r", ch );
          return FALSE;
     }

     one_argument( argument, arg );

     if( is_number( arg ) )
     {
          index = atoi( arg );
          pMob = get_mob_index( index );
     }
     else
     {
          send_to_char( "That is not a number.\n\r", ch );
          return FALSE;
     }

     if( !pMob )
     {
          send_to_char( "No such mobile.\n\r", ch );
          return FALSE;
     }

     SET_BIT( pMob->area->area_flags, AREA_CHANGED );

     /* Remove it from the object list */

     iHash = index % MAX_KEY_HASH;

     /* DEBUG CODE - uncomment this if you have doubts */
     /* printf("\nMobile hash for location %d:\n", iHash);
     for ( tMob = mob_index_hash[iHash]; tMob != NULL; tMob = tMob->next )
          printf("short_desc: %s  vnum: %d\n", tMob->short_descr, tMob->vnum );
*/

     sMob = mob_index_hash[iHash];

     if( sMob->next == NULL ) /* only entry */
          mob_index_hash[iHash] = NULL;
     else if( sMob == pMob ) /* first entry */
          mob_index_hash[iHash] = pMob->next;
     else /* everything else */
     {
          for( iMob = sMob; iMob != NULL; iMob = iMob->next )
          {
               if( iMob ==  pMob )
               {
                    sMob->next = pMob->next;
                    break;
               }
          }
     }

     /* See oedit_delete for why i dont free pMob here */

     /* DEBUG CODE - uncomment this if you have doubts */
     /* printf("\nMobile hash for location %d after removal:\n", iHash);
     for ( tMob = mob_index_hash[iHash]; tMob != NULL; tMob = tMob->next )
          printf("short_desc: %s  vnum: %d\n", tMob->short_descr, tMob->vnum );
*/

     if( top_vnum_mob == index )
          for( i = 1; i < index; i++ )
               if( get_obj_index( i ) )
                    top_vnum_obj = i;

     top_mob_index--;

     /* Now crush all resets */
     count = 0;
     for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
     {
          for( pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next )
          {
               dobj[0] = -1;
               prev = pRoom->reset_first;
               for( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
               {
                    switch( pReset->command )
                    {
                         case 'M':
                              if( pReset->arg1 == index )
                              {
                                   foundmob = TRUE;

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d:\n",
pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */

                                   if( pRoom->reset_first == pReset )
                                   {
                                        pRoom->reset_first = pReset->next;
                                        if( !pRoom->reset_first )
                                             pRoom->reset_last = NULL;
                                   }
                                   else if( pRoom->reset_last == pReset )
                                   {
                                        pRoom->reset_last = prev;
                                        prev->next = NULL;
                                   }
                                   else
                                        prev->next = prev->next->next;

                                   count++;
                                   SET_BIT( pRoom->area->area_flags,
AREA_CHANGED );

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d after
removal:\n", pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */

                              }
                              else
                                   foundmob = FALSE;

                              break;
                         case 'E':
                         case 'G':
                              if( foundmob )
                              {
                                   // printf( "Removing: command: %c  vnum:
%d\n", pReset->command, pReset->arg1 );

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d:\n",
pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */

                                   exist = FALSE;

                                   for( i = 0; dobj[i] != -1; i++ )
                                   {
                                        if( dobj[i] == pReset->arg1 )
                                        {
                                             exist = TRUE;
                                             break;
                                        }
                                   }

                                   if( !exist )
                                   {
                                        dobj[i] = pReset->arg1;
                                        dobj[i + 1] = -1;

                                        /* DEBUG CODE */
                                        /* for( i = 0; dobj[i] != -1; i++ )
                                             printf( "dobj[%d] : %d\n", i,
dobj[i] ); */
                                   }

                                   if( pRoom->reset_first == pReset )
                                   {
                                        pRoom->reset_first = pReset->next;
                                        if( !pRoom->reset_first )
                                             pRoom->reset_last = NULL;
                                   }
                                   else if( pRoom->reset_last == pReset )
                                   {
                                        pRoom->reset_last = prev;
                                        prev->next = NULL;
                                   }
                                   else
                                        prev->next = prev->next->next;

                                   count++;
                                   SET_BIT( pRoom->area->area_flags,
AREA_CHANGED );

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d after
removal:\n", pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
                              }

                              break;
                         case 'P':
                              foundobj = FALSE;

                              for( i = 0; dobj[i] != -1; i++ )
                                   if( dobj[i] == pReset->arg3 )
                                        foundobj = TRUE;

                              if( foundobj )
                              {
                                   printf( "Removing: command: %c  vnum: %d\n",
pReset->command, pReset->arg1 );

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d:\n",
pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */

                                   if( pRoom->reset_first == pReset )
                                   {
                                        pRoom->reset_first = pReset->next;
                                        if( !pRoom->reset_first )
                                             pRoom->reset_last = NULL;
                                   }
                                   else if( pRoom->reset_last == pReset )
                                   {
                                        pRoom->reset_last = prev;
                                        prev->next = NULL;
                                   }
                                   else
                                        prev->next = prev->next->next;

                                   count++;
                                   SET_BIT( pRoom->area->area_flags,
AREA_CHANGED );

                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d after
removal:\n", pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
                              }
                    }
                    prev = pReset;
               }
          }
     }

     /* This is a dumb way to fix what is probably someone elses problem */
     /* The reason for the kludge is that sometime after the exit of
medit_delete */
     /* ch->mount becomes 0x10000000 and I have no idea how or where */
     /*   Narbo */
     if( ch->mount == NULL )
          medit_delete_kludge = ch;

     sprintf( buf, "Removed mobile vnum ^C%d^x and ^C%d^x resets.\n\r", index,
count );
     send_to_char( buf, ch );
     return TRUE;
}


-- 

0o0o0o0o0o0o0o0o0o0o0o00o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0
o Chris Feist      GCS/GMUd-s+:-a--C++++USUH$ULU+++P++L++E-W-N++o?Kw-- o
o Dept 7M52        O?M++V-PS+PEY+PGP+t+5+X-Rtv+b++DI++D++Ge++@hr--!y+  0
0 SS7 Verification                                                     o
o feist@nortel.ca  George Bush: "It's amazing how many people beat you 0 
0                  at golf now that you're no longer president."       o
o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0

