Need help!

Posted by Toy on Sat 07 Feb 2004 11:59 PM — 61 posts, 175,790 views.

#0
I found a few snippets and I installed them on my mud. One was for a banking system, the other for a new currancy system. I put the snippets in, and they worked fine. Now I'm trying to alter the bank code so it'll read gold, copper, and silver. I keep getting strange errors though. the most curious one right now is this one:

[codevoid do_balance( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *banker;
char buf [MAX_STRING_LENGTH];

if ( !( banker = find_banker( ch ) ) )
{
send_to_char( "You're not in a bank!\n\r", ch );
return;
}

if ( IS_NPC( ch ) )
{
sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
do_say( banker, buf );
return;
}
else
{
ch_printf( ch, "You have %d gold in the bank.\n\r", ch->pcdata->balance );
}
return;
}[/code]

That's the very end of the .C file, and it gives me the message:
gcc -c -O -g3 -Wall -Wuninitialized -DNOCRYPT -
bank.c: In function `do_withdraw':
bank.c:304: error: syntax error at end of input
make[1]: *** [bank.o] Error 1
make[1]: Leaving directory `/home/Karl/smaug/dist/
make: *** [all] Error 2

Any clues?

-Toy

USA #1
For starters, you posted the wrong function. Your error is in do_withdraw, you posted do_balance - lets see what do_withdraw looks like (and mark line 304 if you'd be so kind) and we can figure out whats wrong. My first guess from the error you got is a missing ; or " on line 304 though.
#2
[code]void do_withdraw( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *banker;
char arg1[MAX_INPUT_LENGTH];
char buf [MAX_STRING_LENGTH];
int amount;

if ( !( banker = find_banker( ch ) ) )
{
send_to_char( "You're not in a bank!\n\r", ch );
return;
}

if ( IS_NPC( ch ) )
{
sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
do_say( banker, buf );
return;
}

if ( argument[0] == '\0' )
{
do_say( banker, "If you need help, see HELP BANK." );
return;
}

argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );

if ( arg1 == '\0' )
{
sprintf( buf, "%s How much gold, silver, or copper do you wish to withdraw?", ch->name );
do_tell( banker, buf );
return;
}

if ( str_cmp( arg1, "all" ) && !is_number( arg1 ) )
{
sprintf( buf, "%s How much gold do you wish to withdraw?", ch->name );
do_tell( banker, buf );
return;
}

if ( !str_cmp( arg1, "all" ) )
{
amount = ch->pcdata->balance;
}
else
{
amount = atoi( arg1 );
}

if( amount > ch->pcdata->balance )
{
sprintf( buf, "%s But you do not have that much gold in your account!", ch->name );
do_tell( banker, buf );
return;
}

if ( amount <= 0 )
{
sprintf( buf, "%s Oh I see.. you're a comedian.", ch->name );
do_tell( banker, buf );
return;
}
else
{
ch->pcdata->balance -= amount;
ch->gold += amount;
set_char_color( AT_PLAIN, ch );
ch_printf( ch, "You withdraw %d gold.\n\r", amount );
sprintf( buf, "$n withdraws some coins.\n\r" );
act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
save_char_obj( ch );
return;
}

if ( str_cmp( arg2, "all" ) && !is_number( arg2 ) )
{
sprintf( buf, "%s How much silver do you wish to withdraw?", ch->name );
do_tell( banker, buf );
return;
}

if ( !str_cmp( arg2, "all" ) )
{
amount = ch->pcdata->balance;
}
else
{
amount = atoi( arg2 );
}

if( amount > ch->pcdata->balance )
{
sprintf( buf, "%s But you do not have that much silver in your account!", ch->name );
do_tell( banker, buf );
return;
}

if ( amount <= 0 )
{
sprintf( buf, "%s Oh I see.. you're a comedian.", ch->name );
do_tell( banker, buf );
return;
}
else
{
ch->pcdata->balance -= amount;
ch->silver += amount;
set_char_color( AT_PLAIN, ch );
ch_printf( ch, "You withdraw %d silver.\n\r", amount );
sprintf( buf, "$n withdraws some coins.\n\r" );
act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
save_char_obj( ch );
return;
}

if ( str_cmp( arg3, "all" ) && !is_number( arg3 ) )
{
sprintf( buf, "%s How much copper do you wish to withdraw?", ch->name );
do_tell( banker, buf );
return;
}

if ( !str_cmp( arg3, "all" ) )
{
amount = ch->pcdata->balance;
}
else
{
amount = atoi( arg3 );
}

if( amount > ch->pcdata->balance )
{
sprintf( buf, "%s But you do not have that much copper in your account!", ch->name );
do_tell( banker, buf );
return;
}

if ( amount <= 0 )
{
sprintf( buf, "%s Oh I see.. you're a comedian.", ch->name );
do_tell( banker, buf );
return;
}
else
{
ch->pcdata->balance -= amount;
ch->copper += amount;
set_char_color( AT_PLAIN, ch );
ch_printf( ch, "You withdraw %d copper.\n\r", amount );
sprintf( buf, "$n withdraws some coins.\n\r" );
act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
save_char_obj( ch );
return;
}[/code]

I tried adding in some lines here and there after I posted. scapped it and started fresh. my problem is now I get the error at line 389.. which is the last line in the .c file

-Toy
#3
Oh.. I forgot to mention I first posted do_balance because that's the end of the .c file. Line 304 at the time was simply this:

}

That's why I got confused to start with.

-Toy
Canada #4
Found the problem:

else
{
ch->pcdata->balance -= amount;
ch->copper += amount;
set_char_color( AT_PLAIN, ch );
ch_printf( ch, "You withdraw %d copper.\n\r", amount );
sprintf( buf, "$n withdraws some coins.\n\r" );
act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
save_char_obj( ch );
return;
}


Should be:
else
{
ch->pcdata->balance -= amount;
ch->copper += amount;
set_char_color( AT_PLAIN, ch );
ch_printf( ch, "You withdraw %d copper.\n\r", amount );
sprintf( buf, "$n withdraws some coins.\n\r" );
act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
save_char_obj( ch );
return;
}
}


You were missing a closing bracket for the function/for the else statement
#5
Ok, I put the } in and it helped out. Appartently I was missing one on the end of do_deposit to. Ok. Made cleaned and compiled. Everything went in through no problem. Yet, I log into the MUD and try to deposit and amount of silver or copper and it says this:

The banker tells you 'How much gold do you wish to withdraw?'

I know in do_withdraw I put three checks in, one for each coin. Here is the gold one:

[code] if ( str_cmp( arg1, "all" ) && !is_number( arg1 ) )
{
sprintf( buf, "%s How much gold do you wish to withdraw?", ch->name );
do_tell( banker, buf );
return;
}[/code]

All gives me this message:

The banker tells you 'But you do not have that much gold in your account!'

Why isn't it reading the copper or silver?

-Toy
Canada #6
Well, if its not working for copper or silver, you should post the code for copper and silver, makes it much easier. Also, if your going to use [code][/code], you have to check the box below the entry box that says "Forum codes".

Anyways, yeah, if you can post the silver/copper part( or the whole thing) we might be able to better help you.
#7
Once again, sorry about the forum codes.. still trying to get the hang of it.

About the silver and copper, I'm not sure what you mean. All the code I've added into the do_withdraw function I've posted already. Is there anything else you would need? I was under the assumption that what I added to that function would work the way the original snippet did. What I did was I basically copied the original part of the snippet which called for withdrawing gold, and tried making it so it would do the same for copper and silver. I'm still a novice at this, so I assumed it would work right... but it didn't.

-Toy
Canada #8
My bad, you said deposit, and I assumed thats what it was, not the withdraw code, sorry. The thing is, you are not asking at any point which they want, you have no !str_cmp if they are asking for gold, silver, or copper. Since it gets to here:

if ( str_cmp( arg1, "all" ) && !is_number( arg1 ) )
{ 
sprintf( buf, "%s How much gold do you wish to withdraw?", ch->name );
do_tell( banker, buf );
return;
}
If you put, "withdraw 100 silver", it is not all, and arg1 is not a number, so that if check is true, and so it does that code. You need something like:

if ( !str_cmp( arg1, "gold" ) && !is_number( arg1 ) )
{ 
sprintf( buf, "%s How much gold do you wish to withdraw?", ch->name );
do_tell( banker, buf );
return;
}


#9
OK... I added what you suggested, recompiled, and still only accepts gold. Strangly enough though, if I deposit 300 gold I get this for a balance:

You have 300 gold, 1635017078 silver, and 114 copper in the bank.

void do_deposit( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *banker;
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  char arg3[MAX_INPUT_LENGTH];
  char buf [MAX_STRING_LENGTH];
  int amount;
  
  if ( !( banker = find_banker( ch ) ) )
  {
    send_to_char( "You're not in a bank!\n\r", ch );
    return;
  }
  
  if ( IS_NPC( ch ) )
  {
    sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
    do_say( banker, buf );
    return;
  }
  
  if ( argument[0] == '\0' )
  {
    do_say( banker, "If you need help, see HELP BANK." );
    return;
  }

  argument = one_argument( argument, arg1 );
  argument = one_argument( argument, arg2 );
  argument = one_argument( argument, arg3 );

  if ( arg1 == '\0' || arg2 == '\0' || arg3 == '\0' )
  {
    sprintf( buf, "%s How much gold, silver, or copper do you wish to deposit?", ch->name );
    do_tell( banker, buf );
    return;
  }
    
  if ( !str_cmp( arg1, "gold" ) && !is_number( arg1 ) )
  {
    sprintf( buf, "%s How much gold do you wish to deposit?", ch->name );
    do_tell( banker, buf );
    return;
  }
    
  if ( !str_cmp( arg1, "all" ) )
    {
    amount = ch->gold;
    }
  else
    {
    amount = atoi( arg1 );
    }
  
  if ( amount > ch->gold )
    {
    sprintf( buf, "%s Sorry, but you don't have that much gold to deposit.", ch->name );
    do_tell( banker, buf );
    return;
    }
  else
  {
  ch->gold		-= amount;
  ch->pcdata->balance += amount;
  set_char_color( AT_PLAIN, ch );
  ch_printf( ch, "You deposit %d gold.\n\r", amount );
  sprintf( buf, "$n deposits some coins.\n\r" );
  act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  save_char_obj( ch );
  return;
  }

  if ( !str_cmp( arg2, "silver" ) && !is_number( arg2 ) )
  {
    sprintf( buf, "%s How much silver do you wish to deposit?", ch->name );
    do_tell( banker, buf );
    return;
  }
    
  if ( !str_cmp( arg2, "all" ) )
   {
    amount = ch->silver;
   }
  else
   {
    amount = atoi( arg2 );
   }
  
  if ( amount > ch->silver )
  {
    sprintf( buf, "%s Sorry, but you don't have that much silver to deposit.", ch->name );
    do_tell( banker, buf );
    return;
  }
  else
  {
  ch->silver	-= amount;
  ch->pcdata->balance += amount;
  set_char_color( AT_PLAIN, ch );
  ch_printf( ch, "You deposit %d silver.\n\r", amount );
  sprintf( buf, "$n deposits some coins.\n\r" );
  act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  save_char_obj( ch );
  return;
  }

  if ( !str_cmp( arg3, "copper" ) && !is_number( arg3 ) )
  {
    sprintf( buf, "%s How much copper do you wish to deposit?", ch->name );
    do_tell( banker, buf );
    return;
  }
    
  if ( !str_cmp( arg3, "all" ) )
    {
    amount = ch->copper;
    }
  else
    {
    amount = atoi( arg3 );
    }
  
  if ( amount > ch->copper )
  {
    sprintf( buf, "%s Sorry, but you don't have that much copper to deposit.", ch->name );
    do_tell( banker, buf );
    return;
  }
    
  if ( amount <= 0 )
  {
    sprintf( buf, "%s Oh, I see.. you're a comedian.", ch->name );
    do_tell( banker, buf );
    return;
  }
  else
  {
  ch->copper	-= amount;
  ch->pcdata->balance += amount;
  set_char_color( AT_PLAIN, ch );
  ch_printf( ch, "You deposit %d copper.\n\r", amount );
  sprintf( buf, "$n deposits some coins.\n\r" );
  act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  save_char_obj( ch );
  return;
}
}


That's do_deposit. Figure that might help too. Even when u deposit 100 silver, I still get the "you don't have enough gold" message.

-Toy
Canada #10
Thats because you have it sitting all out in the open, as well as your using the wrong checks with the wrong argument. You don't need arg3, as far as I can tell. You need a section for each type, like:
// Gold section
if ( !str_cmp( arg2, "gold" ) )
{
	// Check if they entered "deposit all gold" or "deposit some gold"
	if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much gold do you wish to deposit?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
  	if ( !str_cmp( arg1, "all" ) )
    		amount = ch->gold;
  	else
    		amount = atoi( arg1 );
  
  	if ( amount > ch->gold )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much gold to deposit.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}

  	ch->gold -= amount;
  	ch->pcdata->balance += amount;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You deposit %d gold.\n\r", amount );
  	sprintf( buf, "$n deposits some coins.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
}


If you copy that for silver and gold, that should work as well. However, I notice that they are all deposited into ch->pcdata->balance. How does it know to differentiate the gold from silver or copper?

Hope that helps
#11
OK. I did what you said and it worked, with a minor flaw. If you type "deposit all" with a coin type, it looks like it just goes to a NULL call.

Just need to set up something similiar with withdraw now I guess.

And for your question about do_balance, I haven't really toyed with that yet. Not sure how to get it to read copper and silver. Gonna have to try to hunt down ch->pcdata->balance and see how to alter it abit

-Toy
#12
Alrighty.. just about there... I put everything into withdraw, and got that working. Now comes do_balance.. originally, in order to check the players balance it called to this:

ch->pcdata->balance

which is all fine and dany, yet it only read gold. I went and found the original snippet and found this:

ch_printf( ch,  "You have %s gold, ", num_punct(ch->gold) );
	ch_printf( ch,"%s silver",num_punct(ch->silver));
	ch_printf(ch,", and %s copper coins.\n\r",num_punct(ch->copper) );


what that does is calls to the amount of coins you are currently carrying on you. what I'm trying to do now is get it to read from the ch->pc->balance, but the problem is I think balance only calls to the amount of gold, and I'm snagged as to how to change that. lemme put up the address where the snippet it:

http://www.afkmud.com/scripts/download.php?file=Sadiq/money.txt

that's the currency snippet I used.

-Toy is so close to getting this stupid snippet right he can taste it...
Canada #13
What you want is ch->pcdata->goldbalance, ch->pcdata->silverbalance, ch->pcdata->copperbalance. You'll wanna change do_withdraw and do_deposit, and change ch->pcdata->balance to the appropriate field. You need to also add them to pc_data in mud.h.
#14
Cool. I got everything in and working now. Thanks alot for the help. Now, for my own personal amuzement, I'm going to see if I can get it to make change

ie if I deposit 30,000 copper, I wanna see if I can get it so it'll change into the proper amounts of gold and silver.

This should be amuzing... ;p

-Toy the Ever-amazing at Making His Life Hard
#15
Ok.. ran into a saving problem... whenever you save and quit, you lose your balance.. I got these bug messages

Comm: Loading player data for: Toy (7K)
Log: [*****] FILE: ../player/t/Toy LINE: 29
Log: [*****] BUG: Fread_char: no match: GoldBalance
Log: [*****] FILE: ../player/t/Toy LINE: 29
Log: [*****] BUG: Fread_char: no match: 0
Log: [*****] FILE: ../player/t/Toy LINE: 30
Log: [*****] BUG: Fread_char: no match: SilverBalance0
Log: [*****] FILE: ../player/t/Toy LINE: 31
Log: [*****] BUG: Fread_char: no match: CopperBalance0
Comm: Toy@127.0.0.1((ident not active)) has connected.

in load_char_obj:
ch->pcdata->goldbalance			= 0;


in fread_char:
KEY( "GoldBalance",     ch->pcdata>goldbalance,    fread_number( fp ) );


and in fwrite_char:
    fprintf( fp, "GoldBalance  %d\n",   ch->pcdata->goldbalance );


Ok.. I added those and amended them all to mud.h under pc_data... am I missing something?

-Toy
Canada #16
Hmmm, goldbalance looks ok, just make sure that it is under the 'G' case, because it is sorted by the first letter. It looks like the others are being printed into the file without a space betweem the word and the number, like:
fprintf( fp, "SilverBalance%d\n",   ch->pcdata->silverbalance );
Should be
fprintf( fp, "SilverBalance  %d\n",   ch->pcdata->silverbalance );
#17
Thanks Greven. All I needed was an extra space and it cleared all the bug messages up. Here's what I'm working on right now:

	/* convert cost to g/s/c */
	tmpvalue = maxgold;
	gcost = tmpvalue/10000;
	tmpvalue = tmpvalue%10000;
	scost = tmpvalue/100;
	tmpvalue = tmpvalue%100;
	ccost = tmpvalue;
	if(ch->gold < gcost || ch->silver < scost || ch->copper < ccost){
    tmpvalue = wealth - maxgold;
		conv_currency( ch, tmpvalue);
    send_to_char("You hand your coins to the shopkeeper who quickly makes change.\n\r",ch);


That is from shop.c. It allows the shop keeper to make change from what you buy. Trying to figure out how to put that into do_withdraw, do_deposit, and do_balance because at the moment, if you deposit 3000 copper, it only reads as copper. So if you want to take out the equivent of the amount in any other coin, you'd have to go to a shop and get change first. ;p

-Toy
Canada #18
You could use that pretty easily to make a change command, so they don't have to be taking/giving money from/to the bank, since you will need some way in which to specify what kind of money you want back. As for the actual math formula, I'm far to tired, but you need to work out 3 thing: how much they want in what unit, how much to take out of each unit, and how much to put into each unit(if they want 99 copper but have 0, you must remove 1 silver, give the character 99 copper, and give ch->pcdata->silverbalance 1 copper.)

However, it looks like this is all done already by conv_currency, so you could very easily use that, but I don't know what maxgold or wealth is set to. If you can paste those, I might be able to help you more.
Amended on Mon 09 Feb 2004 06:33 PM by Greven
#19
Having a hard time with this. I even went back to the original snippet. I found the conversions is this:

Mathmatics
----------
100 copper = 1 silver
100 silver = 1 gold
1 gold = 10000 copper

-side note: have to fix that so you need less copper to make silver.

And this also:

tmpvalue = money;
ch->gold = tmpvalue/10000;
tmpvalue=tmpvalue%10000;
ch->silver = tmpvalue/100;
tmpvalue=tmpvalue%100;
ch->copper = tmpvalue;

the part of the code I cut and pasted earlier was for buying pets. I found these lines for wealth and maxgold:

wealth = get_value(ch->gold, ch->silver ,ch->copper);
maxgold = 10 * pet->level * pet->level;

Not sure if this is helping or not. I'm so confused of how to go about doing this. If my help isn't working, my only idea is to look at the original snippet. There is multiple calls for wealth and maxgold, and they seem to pertain to seeing if the carrier has enough money on them.

-Toy
#20
Ok, I'm working on the changing of currency right now. Since I'm still sorta weak at this, I'm having a crisis. I've tried to imitate the calls in the other portions of the bank.c code. Here's what I have so far:

void do_change (CHAR_DATA *ch, char *argument)
{
   int amount;
   int change;
   char buf [MAX_STRING_LENGTH];
   char arg1 [MAX_INPUT_LENGTH];
   char arg2 [MAX_INPUT_LENGTH];
  
   if ( !( banker = find_banker( ch ) ) )
  {
    send_to_char( "You're not in a bank!\n\r", ch );
    return;
  }
  
  if ( IS_NPC( ch ) )
  {
    sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
    do_say( banker, buf );
    return;
  }
  
  if ( argument[0] == '\0' )
  {
    do_say( banker, "If you need help, see HELP BANK." );
    return;
  }

         argument = one_argument( argument, arg1 );
	   argument = two_argument( argument, arg2 );

  if ( arg1 == '\0' || arg2 == '\0' )
  {
    sprintf( buf, "%s How much gold, silver, or copper do you wish to change?", ch->name );
    do_tell( banker, buf );
    return;
  }              

/* Call for changing Gold into Silver and Copper */

  if ( !str_cmp( arg2, "gold" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much gold do you wish to change?", ch->name );
		do_tell( banker, buf );
    		return;
  	}


But then I ran into this snag: How do I add a call to let the person choose between changing into copper or silver? I know how the rest of this code is gonna look in my head: if the player calls to silver, divide the number by 100, and if calls to copper dived by 10000, then alter the changes in all 3 of the pcdata balances.. I just need a shove in the right direction...

-Toy
USA #21
The simple (low coding headache) solution is to not allow a change down from gold at all and only allow copper/silver to be upgraded to the next better value. You do realize you need to recode shop functions to account for your 3 coin types as well right?
Canada #22
What you need to do is to make a function that you can specify which type you want to specify. You can probably copy and adapt convert_currency to do so, I can probably help if you can post the function.
#23
I like the idea of not downgrading from gold, that's save some trouble.

As I mentioned before, in the shops.c file there shows a way of converting currency already from the snippet I installed.

/* convert cost to g/s/c */
tmpvalue = maxgold;
gcost = tmpvalue/10000;
tmpvalue = tmpvalue%10000;
scost = tmpvalue/100;
tmpvalue = tmpvalue%100;
ccost = tmpvalue;

more or less, that reads, from what I can tell that ccost, or copper is equal to a normal value, with silver 100x that, and gold 10000x that. So I'm trying to do is something like this:

if the player wishes to change silver into gold, it'll take the amount of the silver, subtract it from ch->silver, and add it to ch->gold by subtracting the multiple the number of silver by 100 and adding a 1 to the goldbalance per 100x the amount of silver.

so I guess it's supposed to look something like this:


  	if ( !str_cmp( arg1, "all" ) )
    		amount = ch->silver * 10;
  	else
    		amount = atoi( arg1 );

  	if ( amount > ch->silver )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much silver to convert.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}
else
{  	ch->silver -= amount;
  	ch->gold += amount;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You change %d silver into %d gold.\n\r", amount );
  	sprintf( buf, "$n changes some currancy.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
} 


I think I'm on the right path here, just not entirely sure.

-Toy
USA #24
Actually if gold is worth 100 silver an easier way to handle that would be something like:
amount = ch->silver/100
change = ch->silver%100
ch->gold += amount
ch->silver = change

and repeat for copper to silver
#25
Here's what I have so far:

void do_change (CHAR_DATA *ch, char *argument)
{
   CHAR_DATA *banker;
   int amount;
   int change;
   char buf [MAX_STRING_LENGTH];
   char arg1 [MAX_INPUT_LENGTH];
//   char arg2 [MAX_INPUT_LENGTH];
  
   if ( !( banker = find_banker( ch ) ) )
  {
    send_to_char( "You're not in a bank!\n\r", ch );
    return;
  }
  
  if ( IS_NPC( ch ) )
  {
    sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
    do_say( banker, buf );
    return;
  }
  
  if ( argument[0] == '\0' )
  {
    do_say( banker, "If you need help, see HELP BANK." );
    return;
  }

         argument = one_argument( argument, arg1 );
//	   argument = two_argument( argument, arg2 );

  if ( arg1 == '\0' )
  {
    sprintf( buf, "%s How much silver or copper do you wish to change into gold?", ch->name );
    do_tell( banker, buf );
    return;
  }              

/* Call for changing Silver */

  if ( !str_cmp( arg1, "silver" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much silver do you wish to change?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
  	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->silver/100;
            change = ch->silver%100;
	}
  	else
	{    	
	amount = atoi( arg1 );
  	}
  	if ( amount > ch->silver )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}
	else
	{
  	ch->gold += amount;
  	ch->silver = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You change %d silver into %d gold coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
}
}
}



I recompiled with only a
bank.c: In function `do_change':
bank.c:399: warning: `change' might be used uninitialized in this function error message

I logged in and tried to change 2000000 silver into gold... and nothing happens. Looks luck a null. If I put in "change silver" I get this:

The banker tells you 'How much silver do you wish to change?'

Also get a null for "change all silver". Did I put something in the wrong spot?

-Toy
#26
Just realized I posted the wrong bit of code. Posted the stuff I was trying before I added the copper segment. ;p

void do_change (CHAR_DATA *ch, char *argument)
{
   CHAR_DATA *banker;
   int amount;
   int change;
   char buf [MAX_STRING_LENGTH];
   char arg1 [MAX_INPUT_LENGTH];
   char arg2 [MAX_INPUT_LENGTH];
  
   if ( !( banker = find_banker( ch ) ) )
  {
    send_to_char( "You're not in a bank!\n\r", ch );
    return;
  }
  
  if ( IS_NPC( ch ) )
  {
    sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
    do_say( banker, buf );
    return;
  }
  
  if ( argument[0] == '\0' )
  {
    do_say( banker, "If you need help, see HELP BANK." );
    return;
  }

         argument = one_argument( argument, arg1 );
	   argument = two_argument( argument, arg2 );

  if ( arg1 == '\0' || arg2 == '\0' )
  {
    sprintf( buf, "%s How much silver or copper do you wish to change into gold?", ch->name );
    do_tell( banker, buf );
    return;
  }              

/* Call for changing Silver */

  if ( !str_cmp( arg1, "silver" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much silver do you wish to change?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
  	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->silver/100;
            change = ch->silver%100;
	}
  	else
	{    	
	amount = atoi( arg1 );
  	}
  	if ( amount > ch->silver )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}
	else
	{
  	ch->gold += amount;
  	ch->silver = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You change %d silver into %d gold coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
}

/* Call for changing Copper */

  if ( !str_cmp( arg2, "copper" ) )
  {
  if ( str_cmp(arg2, "all") && !is_number( arg2 ) )
  	{
		sprintf( buf, "%s How much copper do you wish to change into silver?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
  	if ( !str_cmp( arg2, "all" ) )
	{
    		amount = ch->copper/1000;
            change = ch->copper%1000;
	}
  	else
	{    	
	amount = atoi( arg2 );
  	}
  	if ( amount > ch->copper )
    	{
    	sprintf( buf, "%s Sorry, but you don't have that much copper to change.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}
	else
	{
  	ch->silver += amount;
  	ch->copper = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You change %d copper into %d silver coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
}
}
}


-Toy
USA #27
A large part of what has this not functioning properly is your arg1/2 handling in the code.

  if ( !str_cmp( arg2, "copper" ) )
  {
  if ( str_cmp(arg2, "all") && !is_number( arg2 ) )

should be more like

  if ( !str_cmp( arg2, "copper" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )

and

  if ( !str_cmp( arg1, "silver" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )

should be more like

  if ( !str_cmp( arg2, "silver" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )

Also in your copper segment

amount = atoi( arg2 );

should be

amount = atoi( arg1 );


Granted, it may still not be flawless after the args are correctly called but you shouldnt be getting no results anymore.
Amended on Thu 12 Feb 2004 01:42 AM by Meerclar
#28
And the fun goes on...

Attempting to change copper still nulls. Changed 2,000 silver into gold and ended up with 2,000 gold and 0 silver with this message:

"You change 2000 silver into 0 gold coins."

So after putting in the changes Meercleer suggested, I'm one step closer.. I hope.

Any other advice/suggestions to finish this monster would be great.

-Toy
Australia Forum Administrator #29
See my recent post about using gdb - put a breakpoint at your function, then step through checking the contents of the variables, until you see what is going wrong.
Canada #30
Also, you want to make sure that your setting change somewhere if they don't enter all, cause it might really screw up how much copper they have if they do it manually.
#31
I know this is gonna probably make me sounds really dumb, but I'm having a problem with gdb. I don't understand how to use it. I tried reading it's help files, and I tried following Nick's post. Can someone gimme some help?

-Toy
Australia Forum Administrator #32
It is almost impossible to solve "a problem".

You need to post a screendump of what you see so we can see what is happening.
#33
*chuckle* I'm sorry, I misworded that. What I ment was I can't figure out how to use gdb at all. I attempted to follow your post on how to use the debugger, but I couldn't even follow that. And until I get an understanding of how to use gdb, I'm pretty much stuck.

-Toy just can't figure anything out today...
Australia Forum Administrator #34
I still prefer to point you in the direction of solving the problem for yourself, then you can solve 100 problems in the time it takes to get one done by someone else on the forum.

In what way are you having problems with gdb? Is it not installed? Does it give an error message? If so, what is it?
#35
Well, I looked up your post of how to debug with gdb, I read down till the part where it said that you can turn on the program with gdb. so I switched into the src folder and attempted to run smaug like this:

gdb smaug
run

it started to run, hit the area.lst section of the mud's startup and stopped because the files for the area weren't in there. I even went so far as to put the area files into the src directory, the game started up, but then nothing happened. It was like I had simply started the .exe file. I couldn't do any gdb commands.

-Toy
Canada #36
Ok, heres what you do:

in the area directory, do this:

gdb ../src/smaug
run (port)

This SHOULD boot the mud, and allow you log into the game. Then, inside GDB, hit ctrl+c, and it should pause the game, and give you a prompt. From there you can probably follow Nick's guide to set a breakpoint inside of your function, and go from there.

Hope that help.
Australia Forum Administrator #37
Yes, since you can't normally run SMAUG itself from the src folder you can hardly expect to debug it from there.

Greven is right, however you probably don't need a port number.

Just go to the area directory, and type:

../src/smaug

Set your breakpoints (in your case the problem function) and then type "run".


eg.

break do_change
run


#38
Ok, I did what you said, I logged in and attempting to change silver, and I got this in gdb

Breakpoint 1, do_change (ch=0xa2577e8, argument=0x22f8d7 "2000 silver")
at bank.c:404
404 if ( !( banker = find_banker( ch ) ) )

then I used backtrace and got this:

#0 do_change (ch=0xa2577e8, argument=0x22f8d7 "2000 silver") at bank.c:404
#1 0x004c8c11 in interpret (ch=0xa2577e8, argument=0x22f8d7 "2000 silver")
at interp.c:730
#2 0x0047e8b0 in game_loop () at comm.c:640
#3 0x0047de7f in main (argc=1, argv=0xa041d60) at comm.c:291

um.. so as 'm not very familiar with this, I'm guessing there is errors in bank.c, interp.c, and comm.c when I do_change?

-Toy
Canada #39
no, backtrace just gives you where the command came from: the game was started in comm.c, your command went through the intererate function in interp.c, and that called do_change.

From here, you want to type n or next to go to the next executable line. It will pause here, lets say it displays:
Quote:
change = silver%10000;
You can type "print silver" and "print change" to see that the variables are right. If they are, follow the next step, and keep checking that everything is right. This should show you how/why its not working when it doesn't go to the place you think it should.
Australia Forum Administrator #40
Exactly!

You might want to display your important fields:

p ch->silver
p ch->gold
p arg1

And so on, and checking that each is what you expect. If so, keep stepping through the function (type "next" or "n") until you get to a place where one should change (eg. "amount") but doesn't, or doesn't change the way you thought it would. Then look very carefully at the line in question.
#41
OK, I think I'm doing this right, lemme post what I've gotten:

Breakpoint 1, do_change (ch=0xa2577e8, argument=0x22f8d7 "all silver")
at bank.c:404
404 if ( !( banker = find_banker( ch ) ) )
(gdb) n
410 if ( IS_NPC( ch ) )
(gdb) n
417 if ( argument[0] == '\0' )
(gdb) n
423 argument = one_argument( argument, arg1 );
(gdb) n
424 argument = one_argument( argument, arg2 );
(gdb) n
435 if ( !str_cmp( arg2, "silver" ) )
(gdb) n
437 if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
(gdb) n
444 if ( !str_cmp( arg1, "all" ) )
(gdb) n
446 amount = ch->silver/100;
(gdb) print amount
$1 = 2281472
(gdb) n
447 change = ch->silver%100;
(gdb) print change
$2 = 2280356
(gdb) n
453 if ( amount > ch->silver )
(gdb) print silver
$3 = silver
(gdb) n
461 ch->gold += amount;
(gdb) print amount
$4 = 20
(gdb) n
462 ch->silver = change;
(gdb) print change
$5 = 0
(gdb)

Now, if I'm reading correctly if I used change all silver, it looks like it works correctly, but these lines confuse me:

446 amount = ch->silver/100;
(gdb) print amount
$1 = 2281472
(gdb) n
447 change = ch->silver%100;
(gdb) print change
$2 = 2280356

can you explain those to me?

-Toy
#42
Quick side note: I logged into the game outaide the debugger and used "change all silver" on 2000 silver. On the character's file it changed to 20 gold and no silver, which is fine, but it gave me this message:

You change 0 silver into 2295260 gold coins.

-Toy
Australia Forum Administrator #43
Quote:

446 amount = ch->silver/100;
(gdb) print amount
$1 = 2281472


I'm pretty sure it does the line you are seeing *after* you press "next" - that is, this is the line that is about to be executed.

Thus, you need to display "amount" *after* that line (press n one more time) - the figure you see there is just the uninitialized variable before the statement is executed.
Australia Forum Administrator #44
You are going well, you almost have it solved.

Just make sure you print the correct variables. Looks like you should be typing:

p ch->silver

not

p silver
Canada #45
Also, for ease of reading, you may want to declar amount as
 int amount = 0;
Just to make sure it starts at 0

P.S. Heh, forums codes == Good
Amended on Fri 13 Feb 2004 07:12 AM by Greven
Australia Forum Administrator #46
Greven, don't forget to check the "forum codes" check box on the forum when you are using things like [code].
#47
Alrighty, after much stress and grief, I've gone through with the debugger and I've narrowed down to 2 last problems/ the first problem is this:

  	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->silver/100;
            change = ch->silver%100;
	}
  	else
	{    	
	amount = ch->silver/100;
	change = ch->silver%100;
  	}


The check for change all works fine. Just not sure how to set it up otherwise. The check for change without the all argument I need help on. Would it be something like

change = ch->silver - amount

and the other problem I've gotten is this one:

  if ( !str_cmp( arg2, "copper" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much copper do you wish to change into silver?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
  	if ( !str_cmp( arg1, "all" ) )


It still NULLS whenever I do any type of change for copper. I used the debugger and the first check it did was this:

Breakpoint 1, do_change (ch=0xa2577e8, argument=0x22f8d7 "all copper")
at bank.c:404
404 if ( !( banker = find_banker( ch ) ) )
(gdb) n
410 if ( IS_NPC( ch ) )
(gdb) n
417 if ( argument[0] == '\0' )
(gdb) n
423 argument = one_argument( argument, arg1 );
(gdb) n
424 argument = one_argument( argument, arg2 );
(gdb) n
435 if ( !str_cmp( arg2, "silver" ) )
(gdb) n
512 }

-Toy
Canada #48
I think the problem if you don't choose silver here is that your using ch->silver, not what they entered, so that may be why its no working, but:

silver = amount/100;
change += amount%100;

if ( change > 100 )
{
//If you have over 100 silver after you get your change,
//convert the other extra silver to gold, and get the difference
	change -=100;
	silver++;
}

I beleive that will work.

As for the second part, when you say its null, its not detecting that you entered copper, that you entered all, that you entered a number, or all of the above?
Amended on Fri 13 Feb 2004 04:12 PM by Greven
#49
I added the code you suggested Greven, and it didn't work. Instead of changing 2000 silver, it made gold and silver 0, gave this message:

"You exchanged you silver for 0 gold."

And then when I tried to change all silver, it worked fine, yet set both gold and silver to 20.

And about copper going to a NULL, when ever you put in either change all copper or change amt copper, nothing happens. It'd be the same as just hitting enter.

-Toy
Canada #50
Do you have a return after the silver part? That might be whats just stopping it. That might be why your not getting to copper. I dunno, I can't see the code.

As for the change stuff, it should have been something like this, I'm really tired, and not so good with math:

  	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->silver/100;
            change = ch->silver%100;
	}
  	else
	{    	
	amount = atoi( arg1 )/100;
	change = atoi( arg1 )%100;

		if ( change > 100 )
		{
//If you have over 100 silver after you get your change,
//convert the other extra silver to gold, and get the difference
			change -=100;
			silver
		}
	}
  	if ( amount > ch->silver )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}


I beleive that should work, sorry, I was using the wrong variables.
#51
Thanks for the help with the changing of silver, its all working right now. Now to the copper issue, I used the debugger after using "change all copper" and it fed me this:

Breakpoint 1, do_change (ch=0xa2577e8, argument=0x22f8d7 "all copper")
at bank.c:406
406 if ( !( banker = find_banker( ch ) ) )
(gdb) n
412 if ( IS_NPC( ch ) )
(gdb) n
419 if ( argument[0] == '\0' )
(gdb) n
425 argument = one_argument( argument, arg1 );
(gdb) n
426 argument = one_argument( argument, arg2 );
(gdb) n
437 if ( !str_cmp( arg2, "silver" ) )
(gdb) n
532 }
(gdb) n
interpret (ch=0xa2577e8, argument=0x22f8d7 "all copper") at interp.c:731
731 end_timer(&time_used);
(gdb) n
735 update_userec(&time_used, &cmd->userec);

I know in the bank.c file, arg1 is all and arg2 is supposed to be either copper or silver, but it appears to only call to silver.

This is the call to copper in the bank.c file:
/* Call for changing Copper */

  if ( !str_cmp( arg2, "copper" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much copper do you wish to change?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
 	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->copper/100;
            change = ch->copper%100;
	}
  	else
	{    	
	amount = atoi( arg1 )/100;
	change = atoi( arg1 )%100;

		if ( change > 100 )
		{
//If you have over 1000 copper after you get your change,
//convert the other extra copper to silver, and get the difference
			change -=100;
			copper;
		}
	}
	
  	if ( amount > ch->copper )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}
	else
	{
  	ch->silver += amount;
  	ch->copper = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You exchanged your copper for %d silver coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
}


Any thoughts?


-Toy
Canada #52
It looks like there might be a return or something after the silver portion. Perhaps your missing a set of {} thats making it go where its not supposed to, I dunno. Is there any return where there shouldn't be?
#53
I think I might have traced it down to this part:
Breakpoint 1, do_change (ch=0xa2577e8, argument=0x22f8d7 "2000 silver")
at bank.c:406
406 if ( !( banker = find_banker( ch ) ) )
(gdb) n
412 if ( IS_NPC( ch ) )
(gdb) n
419 if ( argument[0] == '\0' )
(gdb) n
425 argument = one_argument( argument, arg1 );
(gdb) n
426 argument = one_argument( argument, arg2 );
(gdb) n
437 if ( !str_cmp( arg2, "silver" ) )
(gdb)

it skips over these lines:
  if ( arg1 == '\0' || arg2 == '\0' )
  {
    sprintf( buf, "%s How much silver or copper do you wish to change into gold?", ch->name );
    do_tell( banker, buf );
    return;
  }


could that possibly be it?

-Toy
#54
void do_change (CHAR_DATA *ch, char *argument)
{
   CHAR_DATA *banker;
   int amount = 0;
   int change = 0;
   int silver;
   int copper;
   char buf [MAX_STRING_LENGTH];
   char arg1 [MAX_INPUT_LENGTH];
   char arg2 [MAX_INPUT_LENGTH];
  
   if ( !( banker = find_banker( ch ) ) )
  {
    send_to_char( "You're not in a bank!\n\r", ch );
    return;
  }
  
  if ( IS_NPC( ch ) )
  {
    sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
    do_say( banker, buf );
    return;
  }
  
  if ( argument[0] == '\0' )
  {
    do_say( banker, "If you need help, see HELP BANK." );
    return;
  }

         argument = one_argument( argument, arg1 );
	   argument = one_argument( argument, arg2 );

  if ( arg1 == '\0' || arg2 == '\0' )
  {
    sprintf( buf, "%s How much silver or copper do you wish to change into gold?", ch->name );
    do_tell( banker, buf );
    return;
  }              

/* Call for changing Silver */

  if ( !str_cmp( arg2, "silver" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much silver do you wish to change?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
 	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->silver/100;
            change = ch->silver%100;
	}
  	else
	{    	
	amount = atoi( arg1 )/100;
	change = atoi( arg1 )%100;

		if ( change > 100 )
		{
//If you have over 100 silver after you get your change,
//convert the other extra silver to gold, and get the difference
			change -=100;
			silver++;
		}
	}
	
  	if ( amount > ch->silver )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}
	else
	{
  	ch->gold += amount;
  	ch->silver = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You exchanged your silver for %d gold coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
}

/* Call for changing Copper */

  if ( !str_cmp( arg2, "copper" ) )
  {
  if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
		sprintf( buf, "%s How much copper do you wish to change?", ch->name );
		do_tell( banker, buf );
    		return;
  	}
    
 	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->copper/100;
            change = ch->copper%100;
	}
  	else
	{    	
	amount = atoi( arg1 )/100;
	change = atoi( arg1 )%100;

		if ( change > 100 )
		{
//If you have over 1000 copper after you get your change,
//convert the other extra copper to silver, and get the difference
			change -=100;
			copper++;
		}
	}
	
  	if ( amount > ch->copper )
    	{
    		sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    		do_tell( banker, buf );
    		return;
    	}
	else
	{
  	ch->silver += amount;
  	ch->copper = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You exchanged your copper for %d silver coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
}
}
}
}


I posted this just in case it helps any. :)
-Toy
Australia Forum Administrator #55
Quote:

Mathmatics
----------
100 copper = 1 silver
100 silver = 1 gold
1 gold = 10000 copper


This is what you said everything was worth, and this is how you are doing it ...


if ( !str_cmp( arg1, "all" ) )
  {
     amount = ch->copper/100;
     change = ch->copper%100;
  }  // end of changing all
else
  {  // not changing all     
  amount = atoi( arg1 )/100;
  change = atoi( arg1 )%100;

    if ( change > 100 )
      {
//If you have over 1000 copper after you get your change,
//convert the other extra copper to silver, and get the difference
      change -=100;
      copper;
      }  // end of change > 100

  }  // not changing all
  
if ( amount > ch->copper )
  {
  sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
  do_tell( banker, buf );
  return;
  }  // amount > ch->copper
else
  {
  ch->silver += amount;
  ch->copper = change;
  set_char_color( AT_PLAIN, ch );
  ch_printf( ch, "You exchanged your copper for %d silver coins.\n\r", amount );
  sprintf( buf, "$n changes some currency.\n\r" );
  act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  save_char_obj( ch );
  return;

  }  // enough copper


I've put in some comments and fixed up the indenting so it is easier to see the logic flow.

When you do the "next" in gdb it would be helpful to print out some values, eg. p arg1, p arg2

Also: p ch->copper, p ch->silver


Anyway, the code above doesn't make a huge amount of sense. For one thing, judging by the gdb responses it isn't being executed at all, so there must be a problem further up.

Then you have this:



  change = atoi( arg1 )%100;

    if ( change > 100 )
      {
//If you have over 1000 copper after you get your change,
//convert the other extra copper to silver, and get the difference
      change -=100;
      copper;
      }  // end of change > 100



You cannot have change > 100, because the % operator (modulus) gives the remainder after dividing by 100, it must always be in the range 0 to 99.

I know Greven suggested that, but this is wrong. Also the comment is wrong, you mention 1000 copper, but you are testing for 100.

Then this line doesn't do anything:


copper;


Moving on, you test for "if ( amount > ch->copper )" - why? This is the amount *after* dividing by 100. This is the wrong test.

If they are not changing all, you need to test before the divide.

Then you reply:


sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );


You mean *copper* to change. The whole thing is confusing to read.




Canada #56
See this is where I was tired: I was working at if you had more than 100 silver on you at the time, make it one gold, not in the change, like if you have 105 pennies, make it 1 dollar and 5 cents.


However, it looks like the copper code is inside of the silver code, and that your missing a } after the return at the end of the silver code. should be:
	else
	{
  	ch->gold += amount;
  	ch->silver = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You exchanged your silver for %d gold coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
	}
}


This also means you have to many } at the end of function.

Also, where your setting the gold and silver, you don't have the proper checks to see that they have that much silver.

I think the check should be:

 	if ( !str_cmp( arg1, "all" ) )
	{
    		amount = ch->silver/100;
            	change = ch->silver%100;
	}
  	else
	{    	
		amount = atoi( arg1 )/100;
		change = atoi( arg1 )%100;
// This should be checking if they have enough silver as they say they have	
		if ( atoi(arg1) > ch->silver)
		{
			send_to_char("You do not have enough silver", ch);	
			return;
		}

	}


My apoligies for the bad code, I'll try no to think so much when I'm that tired.
Amended on Fri 13 Feb 2004 10:15 PM by Greven
Australia Forum Administrator #57
In the interests of this forum thread not reaching 5 pages, I've rewritten the do_change function from scratch:


void do_change( CHAR_DATA *ch, char *argument )
{
  
  // do_change snippet written by Nick Gammon
  
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    int value;

    
    if ( !find_banker ( ch ))
      {
      send_to_char( "You're not in a bank!\n", ch );
      return;
      }
  
    if ( IS_NPC( ch ) )
       return;

    

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( ! str_cmp (arg1, "") )
    {
    send_to_char( "Change what?\n\r", ch );
    send_to_char( "Usage: change (<number> | all) [ gold | silver | copper ]\n", ch );
    return;
    }

   // see if they want to change everything

  
   if (! str_cmp (arg1, "all") )
     {
     if (! str_cmp (arg2, "") ) // no argument - change everything
       {
       // change copper to silver
       ch->silver += ch->copper / 100;  // 100 coppers per silver
       ch->copper %= 100;   // remainder is change
       
       // change silver to gold
       ch->gold  += ch->silver / 100;  // 100 silvers per gold
       ch->silver %= 100;   // remainder is change      
      }
    else if (! str_cmp (arg2, "copper") )  
       {
       // change copper to silver
       ch->silver += ch->copper / 100;  // 100 coppers per silver
       ch->copper %= 100;   // remainder is change
      }
    else if (! str_cmp (arg2, "silver") )  
       {
      // change silver to gold
       ch->gold  += ch->silver / 100;  // 100 silvers per gold
       ch->silver %= 100;   // remainder is change      
      }
    else if (! str_cmp (arg2, "gold") )  
       {
      // change gold back to silver
      ch->silver += ch->gold * 100;   // each gold is 100 silvers
      ch->gold = 0;   // no gold left
      }             
    } // end of changing all
  else 
    {
    if (!is_number (arg1))
      {
      send_to_char ("You must supply a number to change (eg. \"change 22 silver\")\n", ch);
      return;
      }
    
    value = atoi (arg1);    // amount they want to change

    if (value <= 0)
      {
      send_to_char ("You can only change 1 or more\n", ch);
      return;
      }

    if (! str_cmp (arg2, "copper") )  
       {
       // change copper to silver
       
       if (ch->copper < value)
         {
        ch_printf (ch, "You only have %i copper!\n", ch->copper);
        return;          
         }
         
       ch->silver += value / 100;  // 100 coppers per silver
       ch->copper -= value;          // take away their copper
       ch->copper += value % 100;   // give back the change
      }
    else if (! str_cmp (arg2, "silver") )  
       {
       // change silver to gold
       
       if (ch->silver < value)
         {
        ch_printf (ch, "You only have %i silver!\n", ch->silver);
        return;          
         }
         
       ch->gold += value / 100;  // 100 silvers per gold
       ch->silver -= value;          // take away their silver
       ch->silver += value % 100;   // give back the change
      }
    else if (! str_cmp (arg2, "gold") )  
       {
      // change gold back to silver
             
       if (ch->gold < value)
         {
        ch_printf (ch, "You only have %i gold!\n", ch->gold);
        return;          
         }
      
      ch->silver += value * 100;   // each gold is 100 silvers
      ch->gold -= value;   // less gold
      }             
    else
      ch_printf (ch, "Change %i what? (gold, silver or copper)\n", value);
   
    } // end of changing a number
  
    
   ch_printf (ch, "You now have %i gold, %i silver, %i copper\n",
           ch->gold, ch->silver, ch->copper);
      

} // end of do_change



What this lets you do is type:


change <-- get help, and show amount you have
change all <-- changes to least number of coins
change all gold <-- changes to silver
change all silver <-- changes to gold
change all copper <-- changes to silver
change 10 gold <-- change a specific amount
change 20 silver <-- change a specific amount
change 30 copper <-- change a specific amount


I'll let you add any more displays you want (eg. to the rest of the room).


Amended on Sat 14 Feb 2004 12:03 AM by Nick Gammon
#58
void do_change (CHAR_DATA *ch, char *argument)
	{
   	CHAR_DATA *banker;
   	char buf [MAX_STRING_LENGTH];
   	char arg1 [MAX_INPUT_LENGTH];
   	char arg2 [MAX_INPUT_LENGTH];
   	int amount = 0;
   	int change = 0;
   	int silver;
   	int copper;
  
   	if ( !( banker = find_banker( ch ) ) )
  	{
    	send_to_char( "You're not in a bank!\n\r", ch );
    	return;
  	}
  
  	if ( IS_NPC( ch ) )
  	{
    	sprintf( buf, "Sorry, %s, we don't do business with mobs.", ch->short_descr );
    	do_say( banker, buf );
    	return;
  	}
  
  	if ( argument[0] == '\0' )
  	{    	
      sprintf( buf, "%s How much silver or copper do you wish to exchange?", ch->name );
    	do_tell( banker, buf );
    	return;
 	}              

      argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );            

/* Call for changing Silver */
  	if ( !str_cmp( arg2, "silver" ) )
  	{
  	if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
	sprintf( buf, "%s How much silver do you wish to change?", ch->name );
	do_tell( banker, buf );
    	return;
  	}
	}

 	if ( !str_cmp( arg1, "all" ) )
	{
    	amount = ch->silver/100;
      change = ch->silver%100;
	}
  	else
	{    	
	amount = atoi( arg1 )/100;
	change = atoi( arg1 )%100;
	}
  	if ( amount > ch->silver )
    	{
    	sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    	do_tell( banker, buf );
    	return;
      }
	if ( change > 99 )
	{
//If you have over 100 silver after you get your change,
//convert the other extra silver to gold, and get the difference
	change -=100;
	silver++;
	}	
	else
	{
  	ch->gold += amount;
  	ch->silver = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You exchanged your silver for %d gold coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
	}

/* Call for changing Copper */
  	if ( !str_cmp( arg2, "copper" ) )
  	{
  	if ( str_cmp(arg1, "all") && !is_number( arg1 ) )
  	{
	sprintf( buf, "%s How much copper do you wish to change?", ch->name );
	do_tell( banker, buf );
    	return;
  	}
	}

 	if ( !str_cmp( arg1, "all" ) )
	{
    	amount = ch->copper/100;
      change = ch->copper%100;
	}
  	else
	{    	
	amount = atoi( arg1 )/100;
	change = atoi( arg1 )%100;
	}
  	if ( amount > ch->copper )
    	{
    	sprintf( buf, "%s Sorry, but you don't have that much silver to change.", ch->name );
    	do_tell( banker, buf );
    	return;
      }
	if ( change > 99 )
	{
//If you have over 100 copper after you get your change,
//convert the other extra copper to silver, and get the difference
	change -=100;
	copper++;
	}	
	else
	{
  	ch->silver += amount;
  	ch->copper = change;
  	set_char_color( AT_PLAIN, ch );
  	ch_printf( ch, "You exchanged your copper for %d silver coins.\n\r", amount );
  	sprintf( buf, "$n changes some currency.\n\r" );
  	act( AT_PLAIN, buf, ch, NULL, NULL, TO_ROOM );
  	save_char_obj( ch );
  	return;
	}
	}


Now that I cleaned up the types and put the amount > ch->silver check into the right spot this might be a bit easier to read. Sorry, still sorta new at this. Anyways I recompiled and tested out. All the calls for changing silver work fine cept for the "all" argument. Simply typing "change all" will now only call to silver, so I believe my issues are in the beginings argument code. Doing tests on it now.

-Toy
#59
didn't see the work you did nick.. I take that last post back. ;p

-Toy
Australia Forum Administrator #60
It occurred to me that you don't want to allow negative numbers (eg, "change -10 gold") as that wouldn't make much sense, so I've added an extra check, in bold, in my earlier post.

Also I put in the stuff about checking for a banker. I don't see why we need to keep the banker pointer, so I didn't do that. Also, I don't see why we need to talk to mobs, so I didn't bother doing that.

And, I see this thread has reached 5 pages. Oh well.