July 20th, 2006
|chetral||06:59 pm - LINK in smaug 1.4a|
I'm working on a smaug code (1.4a).
I have created a new structure named SHIP_DATA and created the routine to load data in it
When I'm going to link it to other "object" of SHIP_DATA type I use the normal link function:
LINK( ship, first_ship, last_ship, next, prev );
next and prev are SHIP_DATA type in the structure SHIP_DATA, first_ship and last_ship are SHIP_DATA type variables declared in db.c and shared in mud.h
When I create a ship and link it, all goes right. When I create the second ship and try to link it I got an error because last_ship is null!
The LINK macro, defined in mud.h, says that the variable passed in the 3rd place (last_ship) at the end of the macro is set equal to the variable passed in the first place (ship). Placing a break after the macro get last_ship = NULL.
Probably I'm missing something, but I can't figure it out!!
Someone can help me?
Current Mood: confused
Ok, I'm not someone who deals in smaug, but I just grabbed the source code and had a look.
so you have something like
ship_data* first_ship = NULL;
ship_data* last_ship = NULL;
/* doing things to set up the ship */
LINK(&ship, first_ship, last_ship, NULL, NULL); // Personally I can't see why next and prev are defined in that macro, they're not used IN the macro.
ship_data* new_ship; /* and lets' take setting up the ship as read */
LINK(new_ship, first_ship, last_ship, NULL, NULL);
So stepping through it, first_ship would be null, so then first_ship is set to point to ship. ship->next then points to null, and link->prev points to NULL (because that's what last is), then last_ship is set to ship. That means we now have first_ship and last_ship pointing to your first ship.
Then with LINK(new_ship, first_ship, last_ship, NULL, NULL), first_ship isn't null, so last->next is pointed to new_ship, then new_ship->next is set to null, and new_ship->prev is set to last, and new_ship is now the new tail.
Personally, I can't see anything wrong with that logic, it's how I'd handle a linked list myself. Now, when I'm doing linked lists, I tend to do one thing that makes life a little more comfortable for myself.... it just makes algorithms a lot easier for me to reason about - I put dummy heads and tails on the list, so first and last are never pointing to null, but just nodes that contain no data. But it doesn't look like smaug has written macros with that sort of design in mind.
Of course, I'm flying a bit blind without some sample code in here... if you show some code of how you create your ships and try linking them in, then we might be better able to help.
|Date:||July 20th, 2006 09:00 pm (UTC)|| |
Yes, I think there are noreason to have problems.
I write here the code, is a bit long:
This is in db.c, called after all areas are loaded
sprintf( shiplist, "%s%s", SHIP_DIR, SHIP_LIST );
if ( ( fpList2 = fopen( shiplist, "r" ) ) == NULL )
perror( SHIP_LIST );
bug( "Unable to open ship list" );
exit( 1 );
for ( ; ; )
strcpy( strShip, fread_word( fpList2 ) );
if ( strShip == '$' )
load_ship_file( last_ship, strShip );
fclose( fpList2 );
void load_ship_file( SHIP_DATA* last_ship, char *fpShip )
sprintf( fpShip2, "%s%s", SHIP_DIR, fpShip );
if ( ( fp = fopen( fpShip2, "r" ) ) == NULL )
perror( fpShip2 );
bug( "Unable to open ship file" );
CREATE( ship, SHIP_DATA, 1 );
ship->first_crew = NULL;
ship->last_crew = NULL;
ship->in_room = 0;
ship->next = NULL;
ship->prev = NULL;
for ( ; ; )
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
if (word == '\0')
switch ( UPPER(word) )
fMatch = TRUE;
fread_to_eol( fp );
if ( !str_cmp( word, "End" ) )
LINK( ship, first_ship, last_ship, next, prev );
if (ship->in_room != 0)
ship = ship_to_room(ship,pRoomIndex);
if ( !fMatch )
sprintf( buf, "Fread_ship: no match: %s", word );
bug( buf, 0 );
I copy also ship_to_room:
SHIP_DATA *ship_to_room( SHIP_DATA *ship, ROOM_INDEX_DATA *pRoomIndex )
LINK( ship, pRoomIndex->first_ship, pRoomIndex->last_ship, next_in_room, prev_in_room );
ship->in_room = pRoomIndex->vnum;
if (ship->in_room == OVERLAND_SPAZIO)
if (ship->map < 0)
ship->map = MAP_SPAZIO;
if (!xIS_SET(ship->act, SHP_ONMAP))
ship->map = -1;
if (xIS_SET(ship->act, SHP_ONMAP))
Note that debugging I found that LAST_SHIP is null the line after the LINK, but there is nothing that can do this!!
Just to finish, the struct of SHIP_DATA from MUD.H
* One ship. - Chetral
SHIP_DATA * next;
SHIP_DATA * prev;
SHIP_DATA * next_in_room;
SHIP_DATA * prev_in_room;
CHAR_DATA * first_crew;
CHAR_DATA * last_crew;
int chockpit; /* cabina di pilotaggio */
SHIP_DATA * master;
char * name;
char * owner;
char * subowner;
char * subowner2;
int engineroom; /* sala macchine */
int turret1; /* prima torretta */
int turret2; /* seconda torretta */
int alloggi; /* alloggi */
char * short_descr;
char * description;
char * action_desc;
char * look_desc; /* descrizione quando di guarda - Chetral */
int serial; /* serial number */
sh_int x; /* Object coordinates on overland maps - Samson 8-21-99 */
sh_int map; /* Which map is it on? - Samson 8-21-99 */
I'm going to wade through this later once I have some time, and am fed... but I will say the follwoing:
Ok, this is only because I'm not really skilled with a debugger yet, but if this was me, I'd be littering each occurance of LINK with regard to ships with debug lines. I'd be testing if the pointers were right and putting it all to a log, or to stdout. It's how I got to understand what was going on when I was hacking some code, and trying to find out why it didn't work. Not the most productive way, but it's good nonetheless.
Better yet, also do those tests with other objects that use LINK but work correctly. See how they behave.
Basically, don't be afraid to litter your code until you're sure it works.
|Date:||July 21st, 2006 06:46 am (UTC)|| |
I will do it when I will be at home. Truly also I write some BUG or LOG near the function I have to check, but the NULL in the link macro is a critical error and stops the program :)
|Date:||July 21st, 2006 09:19 pm (UTC)|| |
At least, now it works, WHY I still do not know :)
The problem was here:
load_ship_file( [b]last_ship[/b], strShip );
As soon as I have declared the funciotn without the last_ship, it worked!
Thanks for the help Tears!