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:
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
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.
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 > 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 > ch->pcdata->balance )
{
sprintf( buf, "%s But you do not have that much copper in your account!", ch->name );
do_tell( banker, buf );
return;
}
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
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!'
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.
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.
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;
}
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?
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
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:
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.
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.
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:
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
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.
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.
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...
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?
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.
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.
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
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.
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.
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?
*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.
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?
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.
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.
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?
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.
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.
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:
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.
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 }
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?
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.
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.
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;
}
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?
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;
}
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.
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:
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.
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).
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.
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.