Login
User Name:

Password:



Register
Forgot your password?
Vote for Us!
auth_update crash
Dec 23, 2017, 10:15 pm
By Remcon
check_tumble
Dec 18, 2017, 7:21 pm
By Remcon
parse description bug
Dec 15, 2017, 10:08 pm
By Remcon
Couple bugs
Dec 12, 2017, 5:42 pm
By Remcon
Bug in disarm( )
Nov 12, 2017, 6:54 pm
By GatewaySysop
LoP 1.46
Author: Remcon
Submitted by: Remcon
LOP 1.45
Author: Remcon
Submitted by: Remcon
LOP Heroes Edition
Author: Vladaar
Submitted by: Vladaar
Heroes sound extras
Author: Vladaar
Submitted by: Vladaar
6Dragons 4.3
Author: Vladaar
Submitted by: Vladaar
Users Online
CommonCrawl, Yahoo!, Sogou

Members: 0
Guests: 5
Stats
Files
Topics
Posts
Members
Newest Member
478
3,708
19,242
612
Jacki72H
Today's Birthdays
There are no member birthdays today.
Related Links
» SmaugMuds.org » General » Coding » lists, single and double how ...
Forum Rules | Mark all | Recent Posts

lists, single and double how to?
< Newer Topic :: Older Topic >

Pages:<< prev 1 next >>
Post is unread #1 Nov 15, 2008, 2:52 am   Last edited Nov 15, 2008, 2:56 am by Llarn
Go to the top of the page
Go to the bottom of the page

Llarn
Apprentice
GroupMembers
Posts63
JoinedNov 25, 2007

Greetings,

Does anyone know if there is a how-to tutorial for creating
single and double lists with C programming that is done
with examples for smaug code? Google, and searching
all the major mud forums resulted in NULL for me.

I have found generic ones for just any C programming out
there that use termiology like nodes and such, and find a
hard time thinking of how it applies to smaug code.

Such as this example on a double linked list
http://cboard.cprogramming.com/showthread.php?p=801670

       
Post is unread #2 Nov 15, 2008, 6:34 am   Last edited Nov 15, 2008, 6:40 am by Keberus
Go to the top of the page
Go to the bottom of the page

Keberus
Conjurer
GroupFUSS Project Team
Posts341
JoinedJun 4, 2005

Llarn said:

Greetings,

Does anyone know if there is a how-to tutorial for creating
single and double lists with C programming that is done
with examples for smaug code? Google, and searching
all the major mud forums resulted in NULL for me.

I have found generic ones for just any C programming out
there that use termiology like nodes and such, and find a
hard time thinking of how it applies to smaug code.

Such as this example on a double linked list
http://cboard.cprogramming.com/showthread.php?p=801670



Ok, not sure exactly what you are looking for but I am guessing that single linked list would be a list that you can only move through one way, and a double linked would be one you can move through 2 ways. Therefore I sumbit this example as a double linked list.

For characters to have a "double linked" list in the struct char_data in mud.h you will see something like:
   CHAR_DATA *next;
   CHAR_DATA *prev;


Notice that the next a prev are both pointers to the char_data type as well.

Continuing, you can also notice that in db.c there are these 2 references:
CHAR_DATA *first_char;
CHAR_DATA *last_char;


Which create valid pointers to the type char_data yet again.

In db.c ...boot db you can find:
   first_char = NULL;
   last_char = NULL;


Which makes sure that first_char and last_char point to nothing.

In db.c function add_char you'll find:
   LINK( ch, first_char, last_char, next, prev );


Which is the code that links the sent ch, to the first_char/last_char delimtered list.

To remove the ch from the list you call:
   UNLINK( ch, first_char, last_char, next, prev );


I believe the first_char and last_char work as min and max paramaters, while the next and prev join each char_data like a chain so you could picture it something like this if there were 5 characters:

first_char                                                  last_char
Keberus    -o-  Keberus2  -o-  Keberus3 -o-  Keberus4  -o-  Keberus5

the prev/nexts would look something like:

Keberus->prev = NULL;
Keberus->next = Keberus2;
Keberus2->prev = Keberus;
Keberus2->next = Keberus3;
Keberus3->prev = Keberus2;
Keberus3->next = Keberus4;
Keberus4->prev = Keberus3;
Keberus4->next = Keberus5;
Keberus5->prev = Keberus4;
Keberus5->next = NULL;

Of course, assuming each Keberus# is a different char_data reference


Hope this helps

**EDIT**
Just browing through smaugfuss src code, in mud.h you can find the LINK macro which looks like:
/* double-linked list handling macros -Thoric */
/* Updated by Scion 8/6/1999 */
#define LINK(link, first, last, next, prev) \
do                                          \
{                                           \
   if ( !(first) )                          \
   {                                        \
      (first) = (link);                     \
      (last) = (link);                      \
   }                                        \
   else                                     \
      (last)->next = (link);                \
   (link)->next = NULL;                     \
   if ((first) == (link))                   \
      (link)->prev = NULL;                  \
   else                                     \
      (link)->prev = (last);                \
   (last) = (link);                         \
} while(0)


Thought that might help as well.
       
Post is unread #3 Nov 15, 2008, 4:11 pm
Go to the top of the page
Go to the bottom of the page

Llarn
Apprentice
GroupMembers
Posts63
JoinedNov 25, 2007

Thanks Keberus I will give that a try.

       
Post is unread #4 Nov 15, 2008, 8:33 pm
Go to the top of the page
Go to the bottom of the page

Llarn
Apprentice
GroupMembers
Posts63
JoinedNov 25, 2007

Hrm,

Keberus I followed you till the add_char part, but then I am unsure how to proceed.

I guess I have to explain further what I am wanting to do so you will know how to
explain.

I am wanting to add a double linked list to a clan file. like vampires.cln.

This is what I have done so far...
clans.h
struct clan_data
added
CLAN_DATA first_kill;
CLAN_DATA last_kill;

db.c
added by first_char
CLAN_DATA *first_kill;
CLAN_DATA *last_kill;

also in db.c within boot_db function added
first_kill = NULL;
last_kill = NULL;

So if I wanted to keep a list of every player a deadly player has killed and be able to display it,
I am unsure how to use LINK and CREATE in the functions that exist to do so.

In raw_kill would adding this save the information?
if (IS_DEADLY(victim))
{
LINK( ch, first_kill, last_kill, next, prev );
}

To display who players have killed would I do something like this?

for(hitlist = first_kill; hitlist; hitlist = last_kill )
pager_printf(ch, "%s\n\r", hitlist);
       
Post is unread #5 Nov 17, 2008, 5:30 am   Last edited Nov 17, 2008, 5:36 am by Keberus
Go to the top of the page
Go to the bottom of the page

Keberus
Conjurer
GroupFUSS Project Team
Posts341
JoinedJun 4, 2005

Ok, now that I know what you want to do, I can be much more specific. As far as I can tell, if you just want to keep track of the people who are killed by someone I think you would be much better off doing it quite differently. Here would be my suggestion for that:

somewhere in mud.h near other stucts like struct char_data put this:
struct pkill_data
{
   PKILL_DATA *next;
   PKILL_DATA *prev;
   char *name;
};


look for structure types comment in mud.h for one like:
typedef struct char_data CHAR_DATA;


and add:
typedef struct pkill_data PKILL_DATA;


in the stucture char_data in mud.h after
   AFFECT_DATA *first_affect;
   AFFECT_DATA *last_affect;


add:
   PKILL_DATA *first_pkill;
   PKILL_DATA *last_pkill;


That will set you up with pretty much all the necessary components. Lets keep going.

In db.c the function clear_char after:
   ch->first_affect = NULL;
   ch->last_affect = NULL;


add:
   ch->first_pkill = NULL;
   ch->last_pkill = NULL;


Now the values are properly initialized to NULL and can be used.
As far as saving them, you would do that in save.c, function fwrite_char.
At the top of fwrite_char after:
   SKILLTYPE *skill = NULL;


add:
   PKILL_DATA *pkill = NULL;


Maybe right after this (in the same function):
   if( ch->desc && ch->desc->host )
      fprintf( fp, "Site         %s\n", ch->desc->host );
   else
      fprintf( fp, "Site         (Link-Dead)\n" );


You could put something like this:
for( pkill = ch->first_pkill; pkill; pkill = pkill->next )
{
   fprintf( fp, "PlayerKill         %s~\n", pkill->name );

}


Now they are saved. So you need to load them in.
In save.c, function fread_char after:
            KEY( "Played", ch->played, fread_number( fp ) );


You can add something like:
            if( !strcmp( word, "PlayerKill" ) )
            {
                PKILL_DATA *pkill;
                CREATE( pkill, PKILL_DATA, 1 );
                pkill->name = fread_string( fp );
                LINK( pkill, ch->first_pkill, ch->last_pkill, next, prev );
                fMatch = TRUE;
                break;
            }


And now they are loaded back in.

Make sure that you free them up in free_char in db.c.
At the top of free_char after:
   MPROG_ACT_LIST *mpact, *mpact_next;
   NOTE_DATA *comments, *comments_next;
   VARIABLE_DATA *vd, *vd_next;


add:
   PKILL_DATA *pkill, *pkill_next;


After:
   for( vd = ch->variables; vd; vd = vd_next )
   {
      vd_next = vd->next;
      delete_variable( vd );
   }


add something like:
   for( pkill = ch->first_pkill; pkill; pkill = pkill_next )
   {
      pkill_next = pkill->next;
      free_pkill( pkill );
   }


Somewhere you'll need to have free_pkill which will look something like:
    void free_pkill( PKILL_DATA *pkill )
    {
         STRFREE( pkill->name );
         DISPOSE( pkill );
    }



So now you should be able to save/load and properly cleanup the memory.

All you have to do is write the functions you want for manipulating the pkills.

The LINK would look similar to:
                LINK( pkill, ch->first_pkill, ch->last_pkill, next, prev );


The UNLINK would look something like:
                UNLINK( pkill, ch->first_pkill, ch->last_pkill, next, prev );

The only thing that can actually change is the very first variables name ( pkill ) which would be whatever you named the variable


Also, to loop through a players pkills you would use something like this:
   for( pkill = ch->first_pkill; pkill; pkill = pkill->next )
   {
        //Show them or whatever in here
   }


.
I really hope this helps ( or I wasted a lot of time for nada )

Later,
KeB
       
Post is unread #6 Nov 18, 2008, 7:45 am
Go to the top of the page
Go to the bottom of the page

Keberus
Conjurer
GroupFUSS Project Team
Posts341
JoinedJun 4, 2005

I was just curious if this ended up helping you Llarn.

Later,
KeB
       
Post is unread #7 Nov 18, 2008, 7:50 pm
Go to the top of the page
Go to the bottom of the page

Llarn
Apprentice
GroupMembers
Posts63
JoinedNov 25, 2007

Wow Thanks,

I haven't had a chance to try it yet, but I definitely will.
       
Post is unread #8 Nov 19, 2008, 10:24 pm
Go to the top of the page
Go to the bottom of the page

kiro_san
Fledgling
GroupMembers
Posts23
JoinedJan 27, 2007

I demand a sticky. Or maybe a diff tut on linked lists? Please? :cry:
       
Post is unread #9 Nov 19, 2008, 11:22 pm
Go to the top of the page
Go to the bottom of the page

Llarn
Apprentice
GroupMembers
Posts63
JoinedNov 25, 2007

Keberus,

It worked perfectly, I thank you for teaching me the
basics of linked lists, even though you had to hold
my hand through the process, with the instructions
you gave me, I can now practice it and get better
when I need to do other lists.

Llarn
       
Post is unread #10 Nov 20, 2008, 10:05 am
Go to the top of the page
Go to the bottom of the page

Keberus
Conjurer
GroupFUSS Project Team
Posts341
JoinedJun 4, 2005

Llarn said:

Keberus,

It worked perfectly, I thank you for teaching me the
basics of linked lists, even though you had to hold
my hand through the process, with the instructions
you gave me, I can now practice it and get better
when I need to do other lists.

Llarn


I'm just glad that I could help.

Later,
KeB
       
Post is unread #11 Dec 26, 2008, 3:31 am   Last edited Dec 26, 2008, 3:57 am by Llarn
Go to the top of the page
Go to the bottom of the page

Llarn
Apprentice
GroupMembers
Posts63
JoinedNov 25, 2007

Hrm with the doubly linked list I have run into a problem.

I have made a command that saves data to different clans, based on the player that
uses the command pcdata->clan.

Thus I have it saved to druid.cln and mage.cln clan files in clan directory.

Now both clans can save the same data, but when one saves the same data, it
should remove it from the other clan's file, only that data though.

So a clan is saving data which is area names from the use of this command
to their clan file.

Now when one clan takes an mob name from another clan, instead of only taking
that mob name, it deletes all the mob names of the other clan to give the one
to the clan that takes it.

I don't see how to get it to only free the one name, a specific name from a
linked list, instead of all names

Im using this....

for ( pkillmob = clan->first_pkillmob; pkillmob; pkillmob = pkillmob->next )
{
if ( !str_cmp( capitalize( pkillmob->name ), capitalize( arg2 ) ) )
{
UNLINK( pkillmob, clan->first_pkillmob, clan->last_pkillmob, next,
prev );
if ( VLD_STR( pkillmob->name ) )
STRFREE( pkillmob->name );
save_clan( clan );
break;
}
}


       
Post is unread #12 Dec 26, 2008, 7:53 am
Go to the top of the page
Go to the bottom of the page

Remcon
Geomancer
GroupAdministrators
Posts1,868
JoinedJul 26, 2005


if ( !str_cmp( capitalize( pkillmob->name ), capitalize( arg2 ) ) )

You can't use capitalize twice in the same line like that it will make it always return true (which means it will remove every name in the list)
Take off the capitalize for pkillmob->name and just leave it on the arg2 and give that a try
       
Post is unread #13 Dec 26, 2008, 7:32 pm
Go to the top of the page
Go to the bottom of the page

Llarn
Apprentice
GroupMembers
Posts63
JoinedNov 25, 2007

Thanks that did it, I would never have noticed that.

       
Post is unread #14 Feb 22, 2009, 10:37 pm
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007

Slightly off topic, but I just noticed in the LINK macro Keberus posted that there is a redundant (last) = (link); statement. Of course this doesn't really affect much, but for optimization's sake... I thought I'd point that out. Unless I'm missing something really obvious about why it's in there twice. :redface:
       
Post is unread #15 Feb 23, 2009, 3:15 am
Go to the top of the page
Go to the bottom of the page

Remcon
Geomancer
GroupAdministrators
Posts1,868
JoinedJul 26, 2005

Looks right to me, the first one is only used if there is no first, so aside from it using it the first time it gets skipped. The second one is the main one used.
       
Post is unread #16 Feb 23, 2009, 3:18 am   Last edited Feb 23, 2009, 3:19 am by Keberus
Go to the top of the page
Go to the bottom of the page

Keberus
Conjurer
GroupFUSS Project Team
Posts341
JoinedJun 4, 2005

/* double-linked list handling macros -Thoric */
/* Updated by Scion 8/6/1999 */
#define LINK(link, first, last, next, prev) \
do                                          \
{                                           \
   if ( !(first) )                          \
   {                                        \
      (first) = (link);                     \
      (last) = (link);                      \
   }                                        \
   else                                     \
      (last)->next = (link);                \
   (link)->next = NULL;                     \
   if ((first) == (link))                   \
      (link)->prev = NULL;                  \
   else                                     \
      (link)->prev = (last);                \
   (last) = (link);                         \
} while(0)



Well, I didn't write the macro, just copied and pasted it, but I am guessing you are talking about the reference inside the if ( !(first) ) part. If so, then, I think you are correct and it can be removed.
       
Post is unread #17 Feb 23, 2009, 4:17 am
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,639
JoinedJan 1, 2002

Removing (last) = (link); in the !(first) section looks safe to me as well. Though I'd really question how much benefit it's going to give. :)
       
Post is unread #18 Feb 23, 2009, 5:30 am
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

While we're at it I'd rearrange the code to eliminate the two if branches: they're really testing the same condition, so might as well put it all in the same place.

And yeah, the gain is probably minimal (but hey, it is redundant), but it's also possible that the compiler could be optimizing it away in the first place. Depends on how clever it is, but you can tell from the code that last isn't used in that control flow, and that the relevant values don't change.
       
Pages:<< prev 1 next >>