Ok, I have put in a spell memorization system in my code. It all works fine and dandy but the one problem is that it saves the sn's of the spells to the pfile. This works great until I add a new skill/spell and it resorts the sn's. So when my next character that had a spell memorized logs in, he'll have a different spell in his memory because the new spell bumped that spell out of it's old sn.
Example:
I mem heal which is sn #90.
I see heal when I type mem to show memorized list.
I log off and have sn 90 saved in my pfile.
A new spell named "haver" is made, and sorted. I hotboot mud, skill table is resorted haver goes into sn 90, pushing heal to 91.
I log back in my player and type mem to show list and it now says haver instead of heal.
Here's where it's saving as sn:
int
set_spell_mem(CHAR_DATA * ch, int sn)
{
int i;
for (i = 0, i < MAX_MEM_SPELLS; i++)
if (ch->pcdata->memorizing[ i] == 0)
{
ch->pcdata->memorizing[ i] = sn;
return TRUE;
}
return FALSE;
}
so it's setting ch->pcdata->memorizing[ i] to sn and I want it set to the slot number. I tried this:
but it didn't work. Any thoughts? The problem is I'm converting this from a envy codebase where there is no sorting on the skills/spells so it never took that into consideration when it saved sn's.
My suggestion would be to save the actual spell name rather than the spell number. You'd need to rework the code a bit to read and store the spell name from input instead of the sn table.
I had thought of that. But I didn't know if I'd be able to figure it all out. How would I set up the for loops to pick out the name rather than the sn?
I'd rather just go with slots numbers. I'm not using any stock spells, so I'm just starting with my own new spells and I can easily put in slot numbers when I add new spells in.
I think it would be easiest to just have it save slot numbers. Save space in pfiles as well. I just need to figure out how to get it to find the slot number through the sn of the spell.
They wont have more than 1 word as the function name so thats one option. You could also use a char * value for storage and read the spell input as one arg with ' delimiters since players have to use them for spells with more than 1 word anyway.
Well, you'd have to be very careful to use SNs anywhere the code expects an SN. I think there is a function called slot_lookup that will translate from slot to SN, which is what you'd want to use. You would set up your data representation and functions however you want, but when you talk to the rest of the code you would need to use the conventions they have. Basically, pick an internal convention and stick with it, and then make sure you do the right thing when talking to the existing functions.
One problem of slots and skill numbers is that they aren't type-safe. Meaning that they can be used interchangeably by accident, even though they really aren't interchangeable at all.
Quote: If I go by names, how would I set it up to look for the arguments?
You said it'd be better to use spell names. How would I set up a char * to be able to use the names to write the names to files? Would it be something like
struct char * ch
for (sn = 0, sn < max_skill, sn++)
sn = skill_table[sn]->name;
return skill_table[sn]->name;
Thats not real, just a psuedo code, but I'm not really sure how to set it to read and write the names to memorization.
No, you would use sn's in memory, but save/load the spell names. It's like how spell effects work currently on, e.g., pfiles: you store names, and convert them to numbers when you read.
- You are using numbers. Are they slot numbers or skill numbers? If they are skill numbers, how are you accounting for the fact that they might change when you add skills and reboot?
- Where do you initialize the memory arrays? You might want to set them all to zero to avoid getting garbage the first time you save (and hence subsequent times you load).
- You might want to only write out elements that actually exist, but that will mean you have to adapt your load function.
You are using numbers. Are they slot numbers or skill numbers? If they are skill numbers, how are you accounting for the fact that they might change when you add skills and reboot?
That's why I'd rather save them by something else. They are saving as skill numbers right now. The reason being once I added a new skill/spell all numbers would be off in the mem list.
Quote:
Where do you initialize the memory arrays? You might want to set them all to zero to avoid getting garbage the first time you save (and hence subsequent times you load).
I believe it just writes out 100 0's when you first create your character
Quote:
You might want to only write out elements that actually exist, but that will mean you have to adapt your load function.
I'd like to do this. It would probably be smoother.
Quote: That's why I'd rather save them by something else. They are saving as skill numbers right now. The reason being once I added a new skill/spell all numbers would be off in the mem list.
So, you are writing out skill numbers, BUT you would rather save them as spell names?
In that case, you can just emulate the code you posted from character reading/saving that translates from names to numbers etc.
Quote: When you save I believe this is what writes out the 100 0's because max_mem_spell is 100, they can't mem anymore then that.
No, that just writes whatever is in those arrays. If you don't set them to zero explicitly when you create the character structure, you will be writing out whatever contents of memory happen to be in that array. (Arrays are not initialized to zero when you create them.)
So, you are writing out skill numbers, BUT you would rather save them as spell names?
In that case, you can just emulate the code you posted from character reading/saving that translates from names to numbers etc.
yes, I would rather change them to names. So I might need a little help figuring out how to emulate the skill fread/fwrite. I'll work on that and see if I can come up with something and post it.
Quote:
No, that just writes whatever is in those arrays. If you don't set them to zero explicitly when you create the character structure, you will be writing out whatever contents of memory happen to be in that array. (Arrays are not initialized to zero when you create them.)
Not sure. I never get any bugs when I create a new character. I'll have to look into it more. When I ported it over from Envy it was late at night and a blur...lol.
**********EDIT *********
I'm not sure how I can write and read the mems. Everything I try isn't right.
********EDIT********
The above code isn't working. It's bugging out and won't read the pfile correctly. Will try again with something else soon.
********************
I believe it's the
if( preload )
word = "End";
that's causing the problem. Here's the bug:
FILE: ../player/g/Greg LINE: 50
BUG: fread_char: no match: End
I took out the if (preload) statement. I didn't get any errors but it always deleted my memorized spells so I'd mem the spells, log out, log back in and have nothing.
I get that in both preloading and loading player data
*****************
EDit
*****************
I know I have to get the for loop in there of max mem spells. I'm not sure how to fit it in.
*****************
EDIT 2
*****************
Then again, the spell fread didn't have any for loops in it. I'm just trying to convert the spell into an sn right now. hmm....
I'm not sure that's the problem. I think that by trying to abort too early on preload, you might be mixing up the reading function. I would try to get things to work for now, and only try to be clever and optimize later.
So what do you suggest? What does it mean to preload or abort to early?
************************************
Quote:
I'm not sure that's the problem. I think that by trying to abort too early on preload, you might be mixing up the reading function. I would try to get things to work for now, and only try to be clever and optimize later.
I am trying to get this to work. I don't know how to optimize lol. Just trying to get it to work and trying everything possible. Been at this forever.
aha! So if I take out that first number to begin with then it should read the word with fread_word? I don't really need that number anyways, it was more for testing purposes.
****EDIT****
and if I did want to keep that number in there, I'd put something like:
int value;
value = fread_number(fp)
and that would read the number first, then put the bsearch after that and that would read the word second?
Ok, it successfully reads and writes the spells, now my problem lies in my do_memorize function. I mem heal, save and quit. Log back in and check pfile, heal is still in pfile as memorized. I use the command memorize and it shows that I have memmed no spells. I save and then check pfile again and it shows no memorized spells.
Here's part of my memorize function. I'm guessing I have to figure out how to call it to read words like in the save.c section:
do_memorize
for (level = 9; level > 0; level--)
{
marker = FALSE;
for (sn = 1; sn < MAX_SKILL; sn++)
{
if ( !skill_table[sn] || skill_table[sn]->spell_level != level )
continue;
total = 0;
for (i = 0; i < MAX_MEM_SPELLS; i++)
{
if ((ch->pcdata->memorized[ i] != 0)
&& (ch->pcdata->memorized[ i] == sn))
{
total++;
none = 0;
}
}
if (total == 0)
continue;
if (marker)
{
if (total < 2)
sprintf(buf, "%s %s\r\n", buf, skill_table[sn]->name);
else
sprintf(buf, "%s %s (x%d)\r\n",buf, skill_table[sn]->name, total);
}
else
{
if (total < 2)
sprintf(buf, "%s (level %2d) %s\r\n", buf, skill_table[sn]->spell_level,
skill_table[sn]->name);
else
sprintf(buf, "%s (level %2d) %s (x%d)\r\n",buf, skill_table[sn]->spell_level,
skill_table[sn]->name, total);
marker = TRUE;
}
}
}
if (none)
sprintf(buf, "%sNone.\r\n\r\n", buf);
else
//sprintf(buf, "%s\r\n", buf);
strcat(buf, "\r\n");
send_to_char(buf, ch);
if (ch->pcdata->memorizing[0] != 0)
{
mudstrlcpy(buf, "", MAX_STRING_LENGTH);
strcat(buf, "And you are currently memorizing the following spells:\r\n");
time_memming = ch->mem_time;
for (i = 0; i < MAX_MEM_SPELLS; i++)
{
if (ch->pcdata->memorizing[ i] != 0)
{
sprintf(buf, "%s %4d seconds (%2d) %s.\r\n",
buf,
time_memming,
skill_table[ch->pcdata->memorizing[ i]]->spell_level,
skill_table[ch->pcdata->memorizing[ i]]->name);
I'm guessing it has to do with the for loops and memorized[ i] parts needing to be called by skill_table[sn]->name again.
Maybe I didn't quite fully fix the fread and fwrite.
I log in, mem heal
save
log out
log back in
check pfile, everything is in there
type mem, nothing in memorize function
save
check pfile, no memorized spells anymore
mem heal again
cast heal on self and it works just fine.
So there's still something wrong with it not reading the sn correctly to show the spell.
You know, it occurs to me that you are writing our "Memorized:" with a colon, but I don't think the colons are skipped when you read in the data -- I could be wrong about that, I really don't remember. It might be worth trying to write without the colon and see what happens.
Which it doesn't really work that well. It will remember the last spell I memorized. I mem spells, they all mem just fine, I save and log off, log back in and I have the last spell I memed in my memory.
How do I update the memorized array? What's the array? It is this right:
There are a few problems here. You're using the variable i, but you never set it to anything, nor do you ever update it. You will want to initialize it to zero somewhere, and every time you make an assignment you want to update it.
But since you have memorized and memorizing, you actually need two variables. I suggest calling them something other than i, like numMemorized.
What I did was, since I was counting the j in the fwrite I set it as the value in the fread. Then I changed the i to a j and since it was counting for every memed spell already, I just used that.
So far, I've been troubleshooting it, but it seems to be working. FINALLY!!! heh.
Good news, it works. Bad news is somehow, I have no idea how, sset save skill table doesn't save through reboot or hotboot now. I tried it on my backup that i made before I switched spell memorization. It worked fine through reboot and hotboot.
I see that's it's saving in the class file, but when I hotboot/reboot, the level goes back up to 101 as if I never saved it. It shows minlevel in skills.dat as the level that I chose it, but it doesn't change in slookup.
i did a diff on tables.c, skills.c and save.c.
SKills.c had onthing, tables.c had nothing, save.c just had the changes to spell memorization.
bah, I thought I had it, now this is going to stump me.
*******EDIT*******
I just put those four changes into my backup folder and now everything works fine. For what I can tell anyways :)
Been watching this with interest -- glad you have it figured out.
Any chance you might be willing to post your memorization system as a snippet? I've looked about for memorization for Smaug with no success.
Either way, glad you got it working.
Regards,
Gadush