practice/learning/teaching

Posted by Frobozz on Fri 31 Dec 2004 01:09 AM — 16 posts, 63,841 views.

#0
Hi!

Right now what Im trying to do is get rid of the do_practice function completely, I already have a "skills" command that breaks different types of skills down into combat/trade/magic/etc... or by damage type. But what I want to do is create a function that allows npc's or pc's to teach a pc a specific skill.

What I can't figure out is how we reach the point where a character has: ch->pcdata->learned[sn].

How would you guys suggest I go about being able to "teach" a pc a skill.

Thanks!
Canada #1
I'm not sure about SMAUG, but SWR has a teach command, you could take a look at that.
#2
Thanks,

That pretty much showed me what I was doing wrong.
#3
Hmm well,

Next question!! I've more or less adapted what SWR had, just to get a feel for what it was doing but now I have a more important question!

Now that I have a character obtaining a skill for the first time after being taught, how do I make that save over a hotboot/reboot/etc?

Right now the mud goes down in the next pulse after I use the teach command. Looks something like this:


Program received signal SIGSEGV, Segmentation fault.
0x080eb2a3 in violence_update () at fight.c:387
387                         ch->desc->character->desc = ch->desc;
(gdb) bt
#0  0x080eb2a3 in violence_update () at fight.c:387
#1  0x0818f042 in update_handler () at update.c:2025
#2  0x080c77f9 in game_loop () at comm.c:675
#3  0x080c6d16 in main (argc=2, argv=0xbffffc94) at comm.c:308
#4  0x4003f177 in __libc_start_main (main=0x80c6904 <main>, argc=2, ubp_av=0xbffffc94, init=0x80490dc <_init>, fini=0x8197030 <_fini>,
    rtld_fini=0x4000e184 <_dl_fini>, stack_end=0xbffffc8c) at ../sysdeps/generic/libc-start.c:129
(gdb) frame 0
#0  0x080eb2a3 in violence_update () at fight.c:387
387                         ch->desc->character->desc = ch->desc;
(gdb) frame 2
#2  0x080c77f9 in game_loop () at comm.c:675
675             update_handler( );
(gdb) frame 3
#3  0x080c6d16 in main (argc=2, argv=0xbffffc94) at comm.c:308
308         game_loop( );
(gdb) frame 4
#4  0x4003f177 in __libc_start_main (main=0x80c6904 <main>, argc=2, ubp_av=0xbffffc94, init=0x80490dc <_init>, fini=0x8197030 <_fini>,
    rtld_fini=0x4000e184 <_dl_fini>, stack_end=0xbffffc8c) at ../sysdeps/generic/libc-start.c:129
129     ../sysdeps/generic/libc-start.c: No such file or directory.
        in ../sysdeps/generic/libc-start.c


The code I used looks like this:


void do_teach (CHAR_DATA *ch, char *argument)
 {
  char arg[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH];
  int sn;

     if ( IS_NPC(ch) )
        return;

    argument = one_argument(argument, arg);

    if ( argument[0] == '\0' )
    {
      send_to_char("\n\r", ch);
      send_to_char("&wSyntax: teach &w<&Cpupil&w> &w<&Cskill&w>\n\r", ch);
      return;
    }
    else
    {
      CHAR_DATA *victim;
      int adept;

    if ( !IS_AWAKE(ch) )
     {
        send_to_char( "You plan on teaching that while sleeping?\n\r", ch );
            return;
     }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
        {
            send_to_char( "Your imaginary friend thanks you for the lessons", ch );
            return;
        }

    sn = skill_lookup( argument );

    if ( sn == -1 )
        {
          act( AT_TELL, "You fail in teaching what you do not know.", victim, NULL, ch, TO_VICT );
          return;
        }


    if ( is_name( skill_tname[skill_table[sn]->type], CANT_PRAC ) )
        {
            act( AT_TELL, "You are unable to teach that skill.", victim, NULL, ch, TO_VICT );
            return;
        }

        adept = 5;

    if ( victim->pcdata->learned[sn] >= adept )
        {
            act( AT_TELL, "$n must learn on their own.", victim, NULL, ch, TO_VICT );
            return;
        }
    if ( ch->pcdata->learned[sn] < 5 )
        {
            act( AT_TELL, "You must learn more before teaching others.", victim, NULL, ch, TO_VICT );
            return;
        }
        else
        {
            victim->pcdata->learned[sn] += int_app[get_curr_int(ch)].learn;
            sprintf( buf, "You teach %s &Y$T.&D", victim->name );
            act( AT_ACTION, buf,
                    ch, NULL, skill_table[sn]->name, TO_CHAR );
            sprintf( buf, "%s teaches you &Y$T&D.", ch->name );
            act( AT_ACTION, buf, victim, NULL, skill_table[sn]->name, TO_CHAR );
        }
    }
    return;
}



USA #4
Only thing that I can spot offhand would be that that function will wreak havok if called on a non-player victim- after you find the victim character you should make a check with IS_NPC or something. Then again, this would be much more likely to simply segfault than to corrupt data, so it's probably not the problem.

Other than that, you might want to check the values of ch, ch->desc, ch->desc->character and ch->desc->character->desc in the gdb backtrace.
#5
These values?



                }
                if (paf->type == gsn_possess)
                {
                    ch->desc->character = ch->desc->original;
                    ch->desc->original  = NULL;
                    ch->desc->character->desc = ch->desc;
                    ch->desc->character->switched = NULL;
                    ch->desc            = NULL;
                }

Canada #6
Ksilyan was refering to this:
(gdb) frame 0
#0  0x080eb2a3 in violence_update () at fight.c:387
387     
Print those in your gdb to see what they are and why its crashing at that spot.
#7
Like this?


(gdb) print ch
$1 = (CHAR_DATA *) 0x83fdb38
(gdb) print ch->desc
$2 = (DESCRIPTOR_DATA *) 0x83fbb00
(gdb) print ch->desc->character
$3 = (CHAR_DATA *) 0x0
(gdb) print ch->desc->character->desc
Cannot access memory at address 0x4c
(gdb)


USA #8
Quote:


Program received signal SIGSEGV, Segmentation fault.
0x080eb2a3 in violence_update () at fight.c:387
387 ch->desc->character->desc = ch->desc;


--------
gdb) print ch->desc->character
$3 = (CHAR_DATA *) 0x0

This would make perfect sense. You are trying to access something from a NULL pointer, which quite obviously wont work :P

I'm not quite sure what that has to do with the skills though...
Amended on Fri 31 Dec 2004 11:39 PM by Nick Cash
USA #9
Indeed. That's your problem, but how you got there baffles me. Surely something has changed besides this one function, because the function you showed us doesn't even touch the descriptor structures.

If you haven't already done so, be sure to make clean, then make again.
#10
Well the violence update refers to the section under gsn_possess. I had taken this skill off the skill table, would that cause this crash?
#11
Hmm.

I put possess back into the skills table (ie skills.dat) and the crash stopped happening. Now why is this so? I have absolutely zero idea.
USA #12
You say that the update function refers to the possess skill... could you show me how? It's possible that you're trying to edit a skill that doesn't exist, thereby editing memory that isn't what you think it is, and thereby corrupting something - for instance, a player descriptor.
#13
line 387 of fight.c where it was breaking is a part of this:


                }
                if (paf->type == gsn_possess)
                {
                    ch->desc->character = ch->desc->original;
                    ch->desc->original  = NULL;
                    ch->desc->character->desc = ch->desc;
                    ch->desc->character->switched = NULL;
                    ch->desc            = NULL;
                }


Canada #14
Check ch->desc->original, that would seem to be null. If thats the case, you need to find out why that if check is evaluating to true. When you removed it, did you remove all references to possess? Looks like gsn_possess might be doubling up with something else, and this is mistaking the affect type as possess instead of what it really is.
USA #15
Most likely, since the possess skill no longer exists, gsn_possess contains -1 or whatever value the lookup function returns (let's call it bad_value.) Check in db.c - somewhere in there, it does all the gsn lookups. (The so-called "GSNs" are in fact cached skill lookups.)

At this point, if you're comparing stuff against a bad value, all bets are off. If you want to remove the possess skill, you should truly remove it by taking out all references to it. I would comment out the line that defines the gsn (in mud.h, I believe) and then go to each compile error, and comment out the relevant section.