code by Darmond Mazule
if you need help in any way with this you can contact me at Lloyd.graham@gmail.com and
i will try my best to help you in any way possible be forewarned i may not reply right away
as i don't check my email every day


I am unsure as to how difficult this will be to install depending on what types you choose
you will ether need just a few things to many changes throughout your code 




****************************************************************************************************************************
TYPE ONE INSTALLATION



in interp.h place
DECLARE_DO_FUN( do_pushup  );


in interp.c place


{ "pushup",            do_pushup,      POS_SITTING,     0,  LOG_NORMAL, 1 },


or something similar just make it look like the rest of the functions there
it can go just about any where but it would probably be best under movement commands,
or Miscellaneous commands
*note* if you have a push command place this after it






****************************************************************************************************************************
TYPE TWO AND THREE INSTALLATION


in interp.h place

DECLARE_DO_FUN( do_pushup  );

----------------------------------------------------------------------------------------------------------------------------
in interp.c place

{ "pushup",            do_pushup,      POS_SITTING,     0,  LOG_NORMAL, 1 },


or something similar just make it look like the rest of the functions there
it can go just about any where but it would probably be best under movement commands,
or Miscellaneous commands
*note* if you have a push command place this after it

----------------------------------------------------------------------------------------------------------------------------
in update.c (or wherever your gain_exp function is) you will need to place this ( i would sagest right under your normal gain_exp function)


void gain_STexp( CHAR_DATA *ch, int gain )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) || ch->perm_stat[STAT_STR] >= 1000 )
	return;

    ch->STexp = ch->STexp + gain;
    while ( ch->perm_stat[STAT_STR] < 1000 && ch->STexp >= 
	STexp_per_STR(ch,ch->perm_stat[STAT_STR]) * (ch->perm_stat[STAT_STR]+1) )
    {
	send_to_char( "Your Strength increases!!  ", ch );
	sprintf(buf,"%s Strength increases %d",ch->name,ch->perm_stat[STAT_STR]);
	log_string(buf);
	sprintf(buf,"$N Strength increases %d!",ch->perm_stat[STAT_STR]);
	wiznet(buf,ch,NULL,WIZ_LEVELS,0,0);
	++ch->perm_stat[STAT_STR];
	save_char_obj(ch);
    }

    return;
}

----------------------------------------------------------------------------------------------------------------------------
now in skills.c or wherever your exp_per_level function is you will need to place this (OK it can probably go in a different place I'm not sure but i don't like to tempt fate so i put similar functions together)


int STexp_per_STR(CHAR_DATA *ch, int STR)
{

   int x, y = 100;

   for( x = 1; x < STR; x++ )
      y += ( x ) + ( x * 3 );
   return y;


}


----------------------------------------------------------------------------------------------------------------------------
now comes the fun part because you are going to have to set it up stexp all throughout your code so that it actually works and records it on players


now in merc.h you will need to place a few things
first  find the         struct	char_data      or similar function and put this right below the normal exp function
*doing a search for exp i find works best here *

    int			STexp;


then find your   int 	 exp_per_level	args( ( CHAR_DATA *ch, int level) );       or the similar exp_per_level function and add this right below


int 	STexp_per_STR	args( ( CHAR_DATA *ch, int STR) );


now the last thing in merc.h find        void	gain_exp	args( ( CHAR_DATA *ch, int gain ) );        and place this below it


void	gain_STexp	args( ( CHAR_DATA *ch, int gain ) );


----------------------------------------------------------------------------------------------------------------------------
now if you want to be able to set someones push-up amounts you will need to go into act_wiz.c and add it to your set commands ( be it mset, set mob, etc ) for me it is mset but best way to find it is just to do a find for exp

in the mset function find
  send_to_char( "    align train thirst hunger drunk full \n\r",				ch );
and change it to this 
  send_to_char( "    STexp\n\r",				ch );

now go further down in the function add this * i put it near another function i made but you can probably put it safely in the stat limiting part of mset just relay put it near stuff in mset that looks the same *



    if ( !str_prefix( arg2, "STexp" ) )
    {
	if ( value < 0 || value > 2000000000 )
	{
	    send_to_char( "STexp range is 0 to 2,000,000,000 points.\n\r", ch );
	    return;
	}
	victim->STexp = value;
	return;
    }

now I'm sure you will want to be able to stat people see how many STexp they have (make sure they aren't exploiting bugs)
so just go ahead and add this to your do_mstat function also, any where in there should do

    sprintf( buf, "STEXP: %d\n\r",
	victim->STexp);
    send_to_char( buf, ch );

thats all for act_wiz.c


----------------------------------------------------------------------------------------------------------------------------
next comes comm.c you will need to find the Nanny function which looks sort of like this
void nanny( DESCRIPTOR_DATA *d, char *argument )				(note this may not be in comm.c but it is on my mud)

you will want this part of the Nanny function
	if ( ch->level == 0 )
put in this somewhere close below 


    ch->STexp	= STexp_per_STR(ch,ch->perm_stat[STAT_STR]);           


( bit of a note you might want to change it to equal something else later once you have tested it as your players will start with a larger then normal amount of STexp to gain a stat but since every ones starting stats are different i left it like this)


----------------------------------------------------------------------------------------------------------------------------
OK next part happens in save.c ( this is important as it saves the amount of push-ups you did ) 

in void fwrite_char( CHAR_DATA *ch, FILE *fp )
find
    fprintf( fp, "Exp  %d\n",	ch->exp			);
and place this below


   fprintf( fp, "STExp  %d\n",	ch->STexp			);


now in void fread_char( CHAR_DATA *ch, FILE *fp )
 find
    KEY( "Sex",		ch->sex,		fread_number( fp ) );
and place this directly below
    KEY( "STExp",	ch->STexp,		fread_number( fp ) );


well that should be all of it whw now to the main function






P.S thanks goes out to Davion Kalhen who after i got the function working helped me
clean up type 1 so it didn't look like junk and i was able to then create type 2 and 3



*************MAIN FUNCTION ( best placed in act_move.c or similar file)**************



			TYPE 1 Random







	Please if you use this piece of code i ask you leave my tag thanks in advance Darmond
				|
				|
				V
/* Darmond's pushup function......... I swear i was not of sound body or mind when i made this*/
void do_pushup( CHAR_DATA *ch, char *argument )
{
    int     chance,number;

    if (ch->position > POS_SITTING)
     {
     send_to_char("Maybe you should sit down.\n\r",ch);
     return;
     }

   send_to_char( "You do a pushup.\n\r", ch );
   WAIT_STATE( ch, 1 * PULSE_VIOLENCE );


    number = number_range(1,20);

    switch(number) 
    {
      case(5):

      chance = 100 / get_curr_stat(ch,STAT_STR);

      if (number_percent() <= chance )
       {
       if (ch->perm_stat[STAT_STR] < 1000)
        {
	++ch->perm_stat[STAT_STR];
        act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
        }
       else
       act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
       }
       break;

      case(10):

       if (ch->perm_stat[STAT_STR] < 100)
        {

	chance = 100 / get_curr_stat(ch,STAT_STR);
       
        if (number_percent() <= chance )
         {
         if (ch->perm_stat[STAT_STR] < 1000)
          {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
         else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
         }
        }
       else if (ch->perm_stat[STAT_STR] >= 100)
        {
	
        chance = 500 / get_curr_stat(ch,STAT_STR);
 
        if (number_percent() <= chance )
	 {
         if (ch->perm_stat[STAT_STR] < 1000)
	  {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
	 else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	 }
        }
        break;

      case(15):

       if (ch->perm_stat[STAT_STR] < 100)
        {
         return;
        }
       else if(ch->perm_stat[STAT_STR] < 500)
        {
          
        chance = 500 / get_curr_stat(ch,STAT_STR);
         
        if (number_percent() <= chance )
         {
         if (ch->perm_stat[STAT_STR] < 1000)
          {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
         else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
         }
        }
       else if (ch->perm_stat[STAT_STR] >= 500)
	{
	
        chance = 750 / get_curr_stat(ch,STAT_STR);
        
        if (number_percent() <= chance )
	 {
         if (ch->perm_stat[STAT_STR] < 1000)
	  {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
	 else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	 }
        }
        break;

       case(20):

        if (ch->perm_stat[STAT_STR] < 500)
         {
         return;
         }
        else if (ch->perm_stat[STAT_STR] < 750)
         {
          
         chance = 750 / get_curr_stat(ch,STAT_STR);
          
         if (number_percent() <= chance )
	  {
          if (ch->perm_stat[STAT_STR] < 1000)
	   {
	   ++ch->perm_stat[STAT_STR];
           act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
           }
	  else
          act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	  }
         }
        else if (ch->perm_stat[STAT_STR] < 1000)
	 {
	
         chance = 1000 / get_curr_stat(ch,STAT_STR);
    
         if (number_percent() <= chance )
	  {
          if (ch->perm_stat[STAT_STR] < 1000)
	   {
	   ++ch->perm_stat[STAT_STR];
           act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
           }
	  else
          act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	  }
         }
	 default: break;
       }
    return;
}



****************************************************************************************************************************
				TYPE 2 set


	Please if you use this piece of code i ask you leave my tag thanks in advance Darmond
				|
				|
				V
/* Darmond's push-up function......... I swear i was not of sound body or mind when i made this*/
void do_pushup( CHAR_DATA *ch, char *argument )
{


    if (ch->position > POS_SITTING)
     {
      send_to_char("Maybe you should sit down.\n\r",ch);
      return;
     }

   send_to_char("you lean forward and start to do a pushup.\n\r",ch);
 //  eprintf_to_char(ch, SECONDS(2), "you slowly lie back and relax as you finish your pushup.\n\r", ch->name);

    if (ch->hit <= (ch->max_hit) / 8  && (ch->move <= 0) && ch->hit != -3 )
     {
      send_to_char("{RYour muscles rip and tear causing massive internal injury's.{w\n\r",ch);
      ch->hit  = -3;
      gain_STexp( ch, -100);
      update_pos( ch );
      return;
     }

    if (get_carry_weight(ch) >= (can_carry_w(ch)/4 )
       && get_carry_weight(ch) < (can_carry_w(ch)/3 ))
     {
      gain_STexp( ch, 1);
     if( ch->move > (ch->max_move)/10 )
      {
       ch->move -= (ch->max_move)/100 ;
      }	 
      else if( ch->move <= 0 ) 
	    {
	     ch->move  = 0;
    	     ch->hit  -= (ch->max_hit)/100;
	     update_pos( ch );
	    }
     }


     if (get_carry_weight(ch) >= (can_carry_w(ch)/3 )
        && get_carry_weight(ch) < (can_carry_w(ch)/2 ))
      { 
       gain_STexp( ch, 2);
      if( ch->move > (ch->max_move)/10 )
       {
        ch->move -= (ch->max_move)/50 ;
       }	 
       else if( ch->move <= 0 ) 
	     {
	      ch->move  = 0;
    	      ch->hit  -= (ch->max_hit)/70;
	      update_pos( ch );
	     }
      }


     if (get_carry_weight(ch) >= (can_carry_w(ch)/2 ))
      {
       gain_STexp( ch, 3);
      if( ch->move > (ch->max_move)/10 )
       {
        ch->move -= (ch->max_move)/30 ;
       }	 
       else if( ch->move <= 0 ) 
	     {
	      ch->move  = 0;
    	      ch->hit  -= (ch->max_hit)/20;
	     }
      }

     if( ch->move <= 0 )
      {
       send_to_char("{Ryour muskles ache and rip.{w\n\r",ch);
       ch->move  = 0;
       ch->hit  -= (ch->max_hit)/20;
       gain_STexp( ch, 5);
      }

     if( ch->move > (ch->max_move)/10 )
      {
       ch->move -= (ch->max_move)/100;
       gain_STexp( ch, 1);
      }

     if( ch->move <= (ch->max_move)/10 )
      {
       ch->move  = 0;
      }
    return;
}


****************************************************************************************************************************
				TYPE 3  random with set



	Please if you use this piece of code i ask you leave my tag thanks in advance Darmond
				|
				|
				V
/* Darmond's pushup function......... I swear i was not of sound body or mind when i made this*/
void do_pushup( CHAR_DATA *ch, char *argument )
{
    int     chance,number;



    if (ch->position > POS_SITTING)
     {
      send_to_char("Maybe you should sit down.\n\r",ch);
      return;
     }

   send_to_char( "You do a pushup.\n\r", ch );


    if (ch->hit < (ch->max_hit) / 8  && (ch->move <= 0) && ch->hit != -3 )
     {
      send_to_char("Your muscles rip and tear causing massive internal injury's.\n\r",ch);
      ch->hit  = -3;
      gain_STexp( ch, -100);
      update_pos( ch );
      return;
     }

    if (get_carry_weight(ch) >= (can_carry_w(ch)/4 )
       && get_carry_weight(ch) < (can_carry_w(ch)/3 ))
     {
      gain_STexp( ch, 1);
     if( ch->move > (ch->max_move)/10 )
      {
       ch->move -= (ch->max_move)/100;
      }	 
      else if( ch->move <= 0 ) 
	    {
	     ch->move  = 0;
    	     ch->hit  -= (ch->max_hit)/100;
	     update_pos( ch );
	    }
     }


     if (get_carry_weight(ch) >= (can_carry_w(ch)/3 )
        && get_carry_weight(ch) < (can_carry_w(ch)/2 ))
      { 
       gain_STexp( ch, 2);
      if( ch->move > (ch->max_move)/10 )
       {
       ch->move -= (ch->max_move)/50;
       }	 
       else if( ch->move <= 0 ) 
	     {
	      ch->move  = 0;
    	      ch->hit  -= (ch->max_hit)/70;
	      update_pos( ch );
	     }
      }


     if (get_carry_weight(ch) >= (can_carry_w(ch)/2 ))
      {
       gain_STexp( ch, 3);
      if( ch->move > (ch->max_move)/10 )
       {
       ch->move -= (ch->max_move)/30;
       }	 
       else if( ch->move <= 0 ) 
	     {
	      ch->move  = 0;
    	      ch->hit  -= (ch->max_hit)/20;
	      update_pos( ch );
	     }
      }

     if( ch->move <= 0 )
      {
       send_to_char("Your muscles ache and rip.\n\r",ch);
       ch->move  = 0;
       ch->hit  -= (ch->max_hit)/20;
       gain_STexp( ch, 5);
      }

     if( ch->move > (ch->max_move)/10 )
      {
       ch->move -= (ch->max_move)/100;
       gain_STexp( ch, 1);
      }

     if( ch->move <= (ch->max_move)/10 )
      {
       ch->move  = 0;
      }





    number = number_range(1,20);

    switch(number) 
    {
      case(5):

      chance = 100 / get_curr_stat(ch,STAT_STR);

      if (number_percent() <= chance )
       {
       if (ch->perm_stat[STAT_STR] < 1000)
        {
	++ch->perm_stat[STAT_STR];
        act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
        }
       else
       act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
       }
       break;

      case(10):

       if (ch->perm_stat[STAT_STR] < 100)
        {

	chance = 100 / get_curr_stat(ch,STAT_STR);
       
        if (number_percent() <= chance )
         {
         if (ch->perm_stat[STAT_STR] < 1000)
          {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
         else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
         }
        }
       else if (ch->perm_stat[STAT_STR] >= 100)
        {
	
        chance = 500 / get_curr_stat(ch,STAT_STR);
 
        if (number_percent() <= chance )
	 {
         if (ch->perm_stat[STAT_STR] < 1000)
	  {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
	 else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	 }
        }
        break;

      case(15):

       if (ch->perm_stat[STAT_STR] < 100)
        {
         return;
        }
       else if(ch->perm_stat[STAT_STR] < 500)
        {
          
        chance = 500 / get_curr_stat(ch,STAT_STR);
         
        if (number_percent() <= chance )
         {
         if (ch->perm_stat[STAT_STR] < 1000)
          {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
         else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
         }
        }
       else if (ch->perm_stat[STAT_STR] >= 500)
	{
	
        chance = 750 / get_curr_stat(ch,STAT_STR);
        
        if (number_percent() <= chance )
	 {
         if (ch->perm_stat[STAT_STR] < 1000)
	  {
	  ++ch->perm_stat[STAT_STR];
          act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
          }
	 else
         act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	 }
        }
        break;

       case(20):

        if (ch->perm_stat[STAT_STR] < 500)
         {
         return;
         }
        else if (ch->perm_stat[STAT_STR] < 750)
         {
          
         chance = 750 / get_curr_stat(ch,STAT_STR);
          
         if (number_percent() <= chance )
	  {
          if (ch->perm_stat[STAT_STR] < 1000)
	   {
	   ++ch->perm_stat[STAT_STR];

           act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
           }
	  else
          act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	  }
         }
        else if (ch->perm_stat[STAT_STR] < 1000)
	 {
	
         chance = 1000 / get_curr_stat(ch,STAT_STR);
    
         if (number_percent() <= chance )
	  {
          if (ch->perm_stat[STAT_STR] < 1000)
	   {
	   ++ch->perm_stat[STAT_STR];
           act( "Your Strength increases!", ch, NULL, NULL, TO_CHAR );
           }
	  else
          act( "You are already as strong as you will get!", ch, NULL, NULL, TO_CHAR );
	  }
         }
	 default: break;
       }

    return;
}






now after installing this more then likely your mud is different then mine so you will have to
tweak the number calculations to fit your needs as well as you might want to change the messages
you get for the actions.








ooo this function here will also be useful for testing i would sagest only giving it to imms or only giving it out for the test phase but ether way it will be an invaluable tool for testing out stats you set up with this system.
*note* this function relay only works with type 2&3 installations

place this in act_info.c


void do_stats( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    if (IS_NPC(ch))
    {
	sprintf(buf,"NPC's dont train.\n\r");
	send_to_char(buf,ch);
	return;
    }

    sprintf(buf, 
    "You have %d strength and trained %d with %d more till your strength increases.\n\r",ch->perm_stat[STAT_STR], ch->STexp,
	(ch->perm_stat[STAT_STR] + 1) * STexp_per_STR(ch,ch->perm_stat[STAT_STR]) - ch->STexp);

    send_to_char(buf,ch);

    return;
}



now in interp.c find

    { "stat",		do_stat,	POS_DEAD,	IM,  LOG_NORMAL, 1 },
add below it * this is important it must be below or you will loose your stat function )
    { "stats",          do_stats,       POS_DEAD,       IM,  LOG_NORMAL, 1 },


now place this in interp.h
DECLARE_DO_FUN( do_stats 	);



After all is said and done clean, make and enjoy