Problems with code i created

Posted by Jason on Fri 05 Mar 2004 10:08 AM — 19 posts, 61,690 views.

#0
ok i made this code in order for people to get there percentage of a skill up a little faster than what the stock code does. What this code does is allows a player to "research" a skill at a library. I had the code working great before i put a timer on it and made it to a skill. if you could please show me what i did wrong with the timer.


void do_research( CHAR_DATA *ch, char *argument )
{
    int sn;
    int adept = 75;
    char arg[MAX_INPUT_LENGTH];
    int chance;


  strcpy( arg, argument );
    
  switch( ch->substate )
  { 
   default:

    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	send_to_char("&RWhat skill would you like to research?\n\r", ch);
	return;
    }

    {
	bool can_prac = TRUE;

	if ( !IS_AWAKE(ch) )
	{
	    send_to_char( "In your dreams, or what?\n\r", ch );
	    return;
	}

	if(!(xIS_SET(ch->in_room->room_flags, ROOM_LIBRARY)))
       {
	    send_to_char( "You need to be in a library to research skills.\n\r", ch );
	    return;

	}

	sn = skill_lookup( argument );
   
        if ( sn == -1 )
        {
           send_to_char("&RYou can't seem to find that skill in any books.\n\r", ch);
	    return;
        }
	
	if ( skill_table[sn]->guild < 0  || skill_table[sn]->guild >= MAX_ABILITY )
        {
	    send_to_char("&RYou cannot learn that skill.\n\r", ch);
	    return;
	}
	
	if ( can_prac &&  !IS_NPC(ch)
	&&   ch->skill_level[skill_table[sn]->guild] < skill_table[sn]->min_level )
	{
           send_to_char("&RYour not ready to research that yet.\n\r", ch);
	    return;
	}

 	if ( is_name( skill_tname[skill_table[sn]->type], CANT_PRAC ) )
	{
	    send_to_char ("&RYou can't find that in any books.\n\r'", ch);
	    return;
	}
    	        chance = IS_NPC(ch) ? ch->top_level
	                 : (int) (ch->pcdata->learned[gsn_research]);
                if ( number_percent( ) < chance )
    		{
    	    	ch->dest_buf = str_dup(arg);
              send_to_char( "&GYou you begin the long proccess of researching a skill.\n\r", ch );
              add_timer ( ch , TIMER_DO_FUN , 0 , do_research , 1 );
    	    	return;
             }
	      send_to_char("&RYou're not quite sure how to do it...\n\r",ch);
	      learn_from_failure( ch, gsn_research );
    	      return;

    	case 1:
       if ( !ch->dest_buf )
    	return;
    	strcpy(arg, ch->dest_buf);
    	DISPOSE( ch->dest_buf);
    	break; /*EVERYTHING WORKED RIGHT UP TO THIS POINT THEN THE CODE STOPPED*/
    		
    	case SUB_TIMER_DO_ABORT:
    	ch->substate = SUB_NONE;
    	send_to_char("&RYou fail to complete your research.\n\r", ch);
    	return;
    }

    ch->substate = SUB_NONE;
               
    if ( number_percent( ) > chance )
    {
       send_to_char( "&RAfter much study you fail to learn anything about your skill.\n\r", ch);
       learn_from_failure( ch, gsn_research );
       return;
    }

    if ( number_percent( ) < chance )
    {
	if ( ch->pcdata->learned[sn] >= adept )
	{
		send_to_char("You've learned everything you can from the books,\n\r", ch);
		send_to_char("you must practice it on your own now.\n\r", ch);
	}
	else
	{
	    ch->pcdata->learned[sn] += 5;
	    act( AT_ACTION, "You gain some knowledge in the skill of $T.",
		    ch, NULL, skill_table[sn]->name, TO_CHAR );

	}
    }
    }
    return;
}
#1
Oh and the way i tested to see where it stopped working was:
send_to_char ("test.\n\r" , ch);

There for it put the word test if it work at that point
USA #2
It doesnt look like you ever actually exit case 1 for your timer case to ever be evaluated. I'd have to do some testing to be sure (and its after 4am and Ive not slept) but I believe the break you put at the end of case 1 is going to be your problem. Might try finding Nick's GDB guide and putting in some breakpoints if you have a *nix setup.
Australia Forum Administrator #3
Your nesting is wrong. You can prove this in vi by putting the cursor over the braces and hitting "%" (go to matching brace), or pasting into the MUSHclient notepad, and choosing "select to matching brace".

Either way, this brace here:


if ( !ch->dest_buf )
    	return;
    	strcpy(arg, ch->dest_buf);
    	DISPOSE( ch->dest_buf);
    	break; /*EVERYTHING WORKED RIGHT UP TO THIS POINT THEN THE CODE STOPPED*/
    		
    	case SUB_TIMER_DO_ABORT:
    	ch->substate = SUB_NONE;
    	send_to_char("&RYou fail to complete your research.\n\r", ch);
    	return;
    }  // <--- this one 


... is matched with one much further up under "default:". Thus the "case SUB_TIMER_DO_ABORT:" is an orphan, not really part of the switch.

#4
well The SUB_TIMER_DO_ABORT does work. everything after that won't
USA #5
The nesting is nonetheless incorrect.

This is why if you ever take a programming class, you'll get indentation indented into your skull... no pun intended. :-)

Seriously though, fix your indentation and braces, and life will be good.
#6
Well might i go about fixing it... I'm not good with timers
USA #7
It's not a timer problem.

It's a brace matching problem, caused by very poor code indentation.
#8
ok well where did i mess up? I can't find it
USA #9
Indent your code, and you'll see where the problem is.

Indenting means to insert tabs (or spaces), like so:

if ( something )
    whatever;
else
{
    if ( something else )
    {
        whatever;
    }
}


This is the badly indented but equivalent expression:


if ( something )
    whatever;
    else
    {
    if ( something else )
    {
        whatever;
        }
    }


Which one is easier to read? Which one can you spot errors more easily with?
#10
ok I did what you said and fix the indents... but i still don't see the problem in this dang code... it is about to drive me nuts. Here is the code with the new indents:

void do_research( CHAR_DATA *ch, char *argument )
{
    int sn;
    int adept = 75;
    char arg[MAX_INPUT_LENGTH];
    int chance;


	strcpy( arg, argument );
    
	switch( ch->substate )
	{ 
	default:

       	if ( IS_NPC(ch) )
		return;

       	if ( argument[0] == '\0' )
       	{
			send_to_char("&RWhat skill would you like to research?\n\r", ch);
			return;
		}

		{
			bool can_prac = TRUE;

			if ( !IS_AWAKE(ch) )
			{
				send_to_char( "In your dreams, or what?\n\r", ch );
				return;
			}

			if(!(xIS_SET(ch->in_room->room_flags, ROOM_LIBRARY)))
			{
				send_to_char( "You need to be in a library to research skills.\n\r", ch );
				return;
			}

		sn = skill_lookup( argument );
  
			if ( sn == -1 )
			{
				send_to_char("&RYou can't seem to find that skill in any books.\n\r", ch);
				return;
			}

			if ( skill_table[sn]->guild < 0  || skill_table[sn]->guild >= MAX_ABILITY )
			{
				send_to_char("&RYou cannot learn that skill.\n\r", ch);
				return;
			}

			if ( can_prac &&  !IS_NPC(ch)
			&&   ch->skill_level[skill_table[sn]->guild] < skill_table[sn]->min_level )
			{
				send_to_char("&RYour not ready to research that yet.\n\r", ch);
				return;
			}

			if ( is_name( skill_tname[skill_table[sn]->type], CANT_PRAC ) )
			{
				send_to_char ("&RYou can't find that in any books.\n\r'", ch);
				return;
			}
		chance = IS_NPC(ch) ? ch->top_level
                 : (int) (ch->pcdata->learned[gsn_research]);

			if ( number_percent( ) < chance )
			{
				ch->dest_buf = str_dup(arg);
				send_to_char( "&GYou you begin the long proccess of researching a skill.\n\r", ch );
				add_timer ( ch , TIMER_DO_FUN , 0 , do_research , 1 );
				return;
			}
			send_to_char("&RYou're not quite sure how to do it...\n\r",ch);
			learn_from_failure( ch, gsn_research );
			return;

			case 1:
			if ( !ch->dest_buf )
			return;
			strcpy(arg, ch->dest_buf);
			DISPOSE( ch->dest_buf);
			break;
    		
			case SUB_TIMER_DO_ABORT:
			ch->substate = SUB_NONE;
			send_to_char("&RYou fail to complete your research.\n\r", ch);
			return;
   
		}

		ch->substate = SUB_NONE;
           
		if ( number_percent( ) > chance )
		{
			send_to_char( "&RAfter much study you fail to learn anything about your skill.\n\r", ch);
			learn_from_failure( ch, gsn_research );
			return;
		}

		if ( number_percent( ) < chance )
		{
			if ( ch->pcdata->learned[sn] >= adept )
			{
				send_to_char("You've learned everything you can from the books,\n\r", ch);
				send_to_char("you must practice it on your own now.\n\r", ch);
			}
			else
			{
			ch->pcdata->learned[sn] += 5;
			act( AT_ACTION, "You gain some knowledge in the skill of $T.",
			ch, NULL, skill_table[sn]->name, TO_CHAR );
			}
		}
	}
	return;
}

do you see the problem?
USA #11
Well, your indents are not quite right... but, well, anyways.

And for the problem, yes, as a matter of fact, I CAN see it... and Nick already pointed it out to you:
Quote:
Either way, this brace here:


if ( !ch->dest_buf )
    	return;
    	strcpy(arg, ch->dest_buf);
    	DISPOSE( ch->dest_buf);
    	break; /*EVERYTHING WORKED RIGHT UP TO THIS POINT THEN THE CODE STOPPED*/
    		
    	case SUB_TIMER_DO_ABORT:
    	ch->substate = SUB_NONE;
    	send_to_char("&RYou fail to complete your research.\n\r", ch);
    	return;
    }  // <--- this one 



... is matched with one much further up under "default:". Thus the "case SUB_TIMER_DO_ABORT:" is an orphan, not really part of the switch.


Not to be discouraging or anything, but do you know how a switch statement works?
#12
sorta..... but i am having problems with them still What would i have to do to fix it?
#13
Oh... And i'm sure you can tell... I am a VERY new coder still i have much to learn.... so all your help is apprieciated
USA #14
To be perfectly honest with you I think you should pick up a book on C or C++ programming, and just learn the language. It might sound pretty harsh, but trust me in the end you'll save yourself a lot of frustration and time. Really, I'm not trying to put you down, I'm just saying you should learn the language before trying to code in it, or you'll be met with only failure and disillusionment. Save yourself the misery and spend a few days learning C first.

A 30 second Google search reveals some nice starting points for free material...

http://www.gustavo.net/programming/c__tutorials.shtml
(Lots of links on that page)

http://www.physics.drexel.edu/courses/Comp_Phys/General/C_basics/c_tutorial.html
(seems to be a more comprehensive manual)

Take my word for it, I know from experience that it's much more enjoyable to do something when you actually know what you're doing. :)
#15
ok i have picked a book up before i can't learn from a book... I learn from trial and error can you please help me and show me what is wrong?
USA #16
Suit yourself, but consider yourself to have been warned. :)

We already told you what the problem is. The first case labels is correct, but the ones after that are inside the wrong pair of brackets. They should be nested at the "top level" of the switch, that is, the part after
switch(xyz){
case ...:
   break;
case ...:
   break;
default:
   break;
}


Go read this for an explanation of conditional expressions in C.
http://www.physics.drexel.edu/courses/Comp_Phys/General/C_basics/c_tutorial.html#conditionals
#17
ok i'm trying to figure out how it is inside the wrong set of brackets.... I've look at many examples just like it... they work and they are setup the same
#18
I got to looking at the code again
I see the problem
Thanx for being so rough i can't beleive i didn't see it
THanx THANX THANX