/*
* $Id: bank.c,v 1.6 2003/05/08 15:58:21 carmine Exp $
*/
/**
* This is the bank inheritable. It handles all the bank transactions
* and other such exciting stuff.
* @author Pinkfish
*/
#include <money.h>
#include <move_failures.h>
#define NAME (string)this_player()->query_name()
#define CAP_NAME (string)this_player()->one_short()
#define POSS (string)this_player()->query_possessive()
#define HANDLER "/obj/handlers/bank_handler"
#define OLD_BANK "/d/am/save/bank"
nosave inherit "/std/room/basic_room";
int total_account, total_made;
nosave int account_cost, percentage;
nosave string bank_name, place;
int do_withdraw(int num, string type);
int do_deposit(string str);
nosave string save_file;
void create() {
account_cost = 0;
percentage = 90;
total_account = 0;
total_made = 0;
bank_name = "Bing's First";
place = "default";
add_help_file("bank");
::create();
} /* create() */
void init() {
add_command( "balance", "" );
add_command( "withdraw", "<number> <string>",
(: do_withdraw($4[0], $4[1]) :) );
add_command( "open", "account" );
add_command( "close", "account" );
add_command( "deposit", "<string>", (: do_deposit($4[0]) :) );
::init();
} /* init() */
/**
* This method returns the amount of money it costs to start an account
* at this bank.
* @return the account cost
*/
int query_account_cost() { return account_cost; }
/**
* This method sets the amount of money that it costs to start an account
* at this bank.
* @param number the cost of starting an account
*/
void set_account_cost( int number ) { account_cost = number; }
/**
* This method queries the percentage the bank charges on transactions.
* @return the percentage the bank charges
*/
int query_percentage() { return percentage; }
/**
* This method sets the percentage the bank charges on transactions.
* @param number the percentage to charge
*/
void set_percentage( int number ) { percentage = number; }
/**
* This method returns the total value of all the accounts.
* @return the totaly value of all the accounts
*/
int query_total_account() { return total_account; }
/**
* This method returns the amount of money the bank has made off the
* players.
* @param total_made the amount of money mae
*/
int query_total_made() { return total_made; }
string query_bank_name() { return bank_name; }
void set_bank_name( string word ) { bank_name = word; }
string query_place() { return place; }
string query_money_place() { return query_place(); }
void set_place( string word ) { place = word; }
string query_save_file() { return save_file; }
void set_save_file( string word ) {
save_file = word;
if ( file_size( save_file +".o" ) > 0 )
unguarded((: restore_object, save_file :));
} /* set_save_file() */
void do_save() {
if ( !save_file ) {
return;
}
unguarded( (: save_object, save_file :) );
} /* do_save() */
int get_account() {
int amount;
if ( amount = (int)this_player()->query_property( "bank "+ OLD_BANK ) ) {
HANDLER->adjust_account( NAME, bank_name, amount );
this_player()->remove_property( "bank "+ OLD_BANK );
total_account += amount;
do_save();
}
return (int)HANDLER->query_account( NAME, bank_name );
} /* get_account() */
int set_account( int amount ) {
HANDLER->set_account( NAME, bank_name, amount );
} /* set_account() */
int do_balance() {
int amount;
amount = get_account();
if ( amount < 0 ) {
notify_fail( "You do not have an account here.\n" );
return 0;
}
if ( !amount ) {
this_player()->add_succeeded_mess(this_object(),
({ "Your account is empty.\n",
"$N checks the balance of $p account.\n" }), ({ }) );
return 1;
}
this_player()->add_succeeded_mess(this_object(),
({ "You have "+ (string)MONEY_HAND->money_value_string( amount, place ) +
" in your account.\n",
"$N checks the balance of $p account.\n" }), ({ }) );
return 1;
} /* do_balance() */
int do_withdraw( int number, string type ) {
int amount;
int best;
int total;
object money;
total = get_account();
if ( total < 0 ) {
notify_fail( "You do not have an account here.\n" );
return 0;
}
if ( number <= 0 ) {
notify_fail( "You must withdraw something.\n" );
return 0;
}
money = clone_object( MONEY_OBJECT );
money->set_money_array( (mixed *)MONEY_HAND->query_values_in( place ) );
if ( ( best = (int)money->find_best_fit( type ) ) == -1 ) {
notify_fail( "That currency is not legal tender here. Sorry.\n" );
money->dest_me();
return 0;
}
type = ( (mixed *)money->query_money_array() )[ best ];
amount = number * ( (mixed *)money->query_money_array() )[ best + 1 ];
if ( ( amount > total ) ||
( amount < 0 ) ) {
notify_fail( "You don't have enough money in your account. Sorry.\n" );
money->dest_me();
return 0;
}
money->set_money_array( ({ type, number }) );
set_account( total - amount );
total_account -= amount;
do_save();
this_player()->add_succeeded_mess(this_object(),
({ "You withdraw "+ (string)money->short() +".\n" +
"You have "+ (string)MONEY_HAND->money_value_string( get_account(),
place ) +
" in your account after the withdrawal.\n",
"$N withdraws some money from $p account.\n"
}), ({ }) );
if ( (int)money->move( this_player() ) != MOVE_OK ) {
write( "You are too heavily burdened to collect the money, so the teller "+
"puts it on the counter for you.\n" );
money->move( this_object() );
}
this_player()->save();
return 1;
} /* do_withdraw() */
int do_deposit( string words ) {
int amount;
int total;
int tmp;
mixed money;
object *tender;
object legal;
object illegal;
string howmuch;
total = get_account();
if ( total < 0 ) {
notify_fail("You don't have an account here.\n");
return 0;
}
money = (mixed)MONEY_HAND->parse_money( words, this_player(), place );
if ( intp( money ) ) {
switch( money ) {
case NO_MATCH :
return notify_fail( "You do not have \""+ words +"\".\n" );
case NO_MONEY :
return notify_fail( "You can only deposit money.\n" );
default :
return notify_fail( "You can only deposit legal tender.\n" );
}
}
// Figure out the legal tender
if (!place) {
place = "default";
}
tender = MONEY_HAND->filter_legal_tender( money, place);
legal = tender[0];
illegal = tender[1];
if (legal) {
amount = legal->query_value_in(place);
if (place != "default") {
amount += legal->query_value_in("default");
}
// Minimum amount added to prevent depositing 1c 1000 times to avoid
// charges.
if(amount < 200) {
if( legal->move( this_player() ) != MOVE_OK ) {
legal->move( environment( this_player() ) );
tell_object( this_player(), "You lose hold of some coins and "
"they tumble to the floor.\n" );
tell_room( environment( this_player() ), this_player()->one_short() +
"accidentally drops some coins.\n", this_player() );
}
if(illegal)
if( illegal->move( this_player() ) != MOVE_OK ) {
illegal->move( environment( this_player() ) );
tell_object( this_player(), "You lose hold of some coins and "
"they tumble to the floor.\n" );
tell_room( environment( this_player() ), this_player()->one_short() +
"accidentally drops some coins.\n", this_player() );
}
add_failed_mess("That is too small an amount to deposit.\n");
return 0;
}
tmp = ( amount * ( 100 - percentage ) ) / 100;
total_made += tmp;
amount = amount - tmp;
set_account( total + amount );
total_account += amount;
do_save();
}
// Give them back their illegal money and zap the other stuff.
if (illegal) {
if( illegal->move( this_player() ) != MOVE_OK ) {
illegal->move( environment( this_player() ) );
tell_object( this_player(), "You lose hold of some coins and "
"they tumble to the floor.\n" );
tell_room( environment( this_player() ), this_player()->one_short() +
"accidentally drops some coins.\n", this_player() );
}
}
if (legal) {
howmuch = legal->the_short();
legal->move( "/room/rubbish" );
this_player()->save();
} else {
add_failed_mess("Unable to find any legal money to deposit.\n");
return 0;
}
write( "You give the teller "+ howmuch +".\n" );
write( "After expenses, this leaves "+ (string)MONEY_HAND->
money_value_string( amount, place ) +".\n" );
this_player()->add_succeeded_mess(this_object(),
({ "$N $V "+words+".\n"
"This gives a total of " +
MONEY_HAND->money_value_string(total + amount, place ) +
" in your account.\n",
"$N deposit$s some money into $p account.\n" }), ({ }) );
return 1;
} /* do_deposit() */
int do_open() {
int amount;
object money;
if ( get_account() >= 0 ) {
notify_fail( "You already have an account here.\n" );
return 0;
}
if ( account_cost ) {
if ( !( money = present( MONEY_ALIAS, this_player() ) ) ) {
notify_fail( "You do not have any money.\n" );
return 0;
}
amount = (int)money->query_value_in( place );
if ( place != "default" )
amount += (int)money->query_value_in( "default" );
if ( amount < account_cost ) {
notify_fail( "You do not have enough money to open an account.\n" );
return 0;
}
write( "It will cost you "+ (string)MONEY_HAND->money_value_string(
account_cost, place ) +" to open the account.\nDo you still wish to "+
"open an account here? " );
input_to( "check_open" );
return 1;
}
set_account( 0 );
this_player()->add_succeeded_mess(this_object(),
"$N $V an account.\n", ({ }) );
return 1;
} /* do_open() */
int check_open( string word ) {
object money;
word = lower_case( word );
if (word [ 0 ] == /* "n" */ 110 ) {
write( "Okay, not opening an account.\n" );
return 1;
}
if ( word[ 0 ] != /* "y" */ 121 ) {
write( "Do you want to open an account? Answer \"yes\" or \"no\".\n" );
input_to( "check_open" );
return 1;
}
set_account( 0 );
write( "You now have an account here.\n" );
money = present( MONEY_ALIAS, this_player() );
MONEY_HAND->pay_amount_from( account_cost, money, place );
total_made += account_cost;
do_save();
this_player()->save();
return 1;
} /* check_open() */
int do_close() {
int total;
object money;
total = get_account();
if ( total < 0 ) {
notify_fail( "You do not have an account here.\n" );
return 0;
}
if ( total ) {
if ( money = (object)MONEY_HAND->make_new_amount( total, place ) ) {
write( "You receive "+ (string)money->short() +" on closing "+
"your account.\n" );
if ( (int)money->move( this_player() ) != MOVE_OK ) {
write( "You are too heavily burdened to accept all that money, so "+
"the teller puts it on the counter for you.\n" );
money->move( this_object() );
}
} else {
write( "The amount of money in your account was not even worth a "+
"coin of the lowest denomination in the local currency. Sorry.\n"+
"Your account is now closed.\n" );
total_made += total;
}
total_account -= total;
} else
write( "You close your account.\n" );
this_player()->add_succeeded_mess(this_object(),
"$N $V an account.\n", ({ }) );
set_account( -1 );
do_save();
this_player()->save();
return 1;
} /* do_close() */
mixed *stats() {
return ::stats() + ({
({ "account cost", account_cost }),
({ "percentage", percentage }),
({ "total accounts", total_account }),
({ "total made", total_made }),
({ "bank name", bank_name }),
({ "place", place }),
({ "save file", save_file }) });
} /* stats() */
int make_bank_robbers() {
int i, amount, loss, number, percent_loss, total;
string player_name;
object *bags, *money, *players, *robbers;
mixed *mon_array;
percent_loss = 2 + random( 4 );
players = users();
for ( i = 0; i < sizeof( players ); i++ ) {
player_name = (string)players[ i ]->query_name();
if ( ( amount = (int)HANDLER->query_account( player_name, bank_name ) ) ) {
switch( amount ) {
case 1 .. 10:
loss = 0;
break;
case 11 .. 100:
loss = ( amount * percent_loss ) / 100;
break;
case 101 .. 1000:
loss = ( amount * percent_loss * 2 ) / 100;
break;
case 1001 .. 10000:
loss = ( amount * percent_loss * 3 ) / 100;
break;
case 10001 .. 100000:
loss = ( amount * percent_loss * 4 ) / 100;
break;
default:
loss = ( amount * percent_loss * 5 ) / 100;
}
HANDLER->adjust_account( player_name, bank_name, -loss );
total += loss;
}
}
if ( !total ) return 0;
if ( !( number = total / 10000 ) ) number = 1;
if ( number > 5 ) number = 5;
total_account -= total;
amount = total / 3;
total_made += 2 * amount;
do_save();
mon_array = (mixed *)MONEY_HAND->create_money_array( amount / number, place );
bags = allocate( number );
money = allocate( number );
robbers = allocate( number );
for ( i = 0; i < number; i++ ) {
money[ i ] = clone_object( MONEY_OBJECT );
money[ i ]->set_money_array( mon_array );
bags[ i ] = clone_object( "/obj/container" );
bags[ i ]->set_name( "bag" );
bags[ i ]->set_short( "money bag" );
bags[ i ]->add_adjective( "money" );
bags[ i ]->add_property( "determinate", "a " );
bags[ i ]->set_main_plural( "money bags" );
bags[ i ]->set_long( "This is a roughly sewn sacking bag with a big "+
"\"$\" sign on it.\n" );
bags[ i ]->set_weight( 10 );
bags[ i ]->set_max_weight( 3 * (int)money[ i ]->query_weight() + 10 );
robbers[ i ] = clone_object( "/obj/monster" );
robbers[ i ]->set_name( "robber" );
robbers[ i ]->set_short( "bank robber" );
robbers[ i ]->add_adjective( "bank" );
robbers[ i ]->add_property( "determinate", "a " );
robbers[ i ]->set_main_plural( "bank robbers" );
robbers[ i ]->set_long( "This is a bank robber. You can tell by the "+
"stripey jersey and the mask over his eyes.\n" );
robbers[ i ]->set_race( "human" );
robbers[ i ]->set_guild( "thief" );
robbers[ i ]->set_gender( 1 + random( 1 ) );
robbers[ i ]->set_level( 20 + random( 30 ) + random( 40 ) );
robbers[ i ]->reset_all();
money[ i ]->move( bags[ i ] );
bags[ i ]->move( robbers[ i ] );
robbers[ i ]->move( this_object() );
}
return amount;
} /* make_bank_robbers() */