// bank.c // A basic bank object. Players can open an account, receiving a bank card. // The bank card is an autoloading object that keeps track of how much // money they have deposited. At the bank, players can withdraw or deposit // funds. // The bank has a create function which sets the euid of the object. Any // file than inherits this file needs to ::create() in its create function. // Note that the bank does not store the account data internally. Instead, // each player's account data is stored in his bank card. This makes lookup // faster but it does mean the player has to keep his card safe. // Created by Mobydick@TMI-2, 8-28-92 #define SIGN "/obj/coinval_sign" #include <move.h> #include <mudlib.h> #include <money.h> inherit ROOM ; inherit COINVALUE ; void create() { object sign ; ::create() ; seteuid(getuid()) ; sign = clone_object(SIGN) ; sign->set_location(file_name(this_object())) ; } void init() { add_action ("open_account", "open") ; add_action ("deposit", "deposit") ; add_action ("withdraw", "withdraw") ; } // Open_account lets the player open his bank account. It gives him a bank // card which is where his account data is stored. The fee is set at 25 // gold pieces but you can change that very easily if you desire. int open_account(string str) { int i ; object ob ; if (!str || str != "account") { notify_fail ("Open what?\n") ; return 0 ; } if (present("bank card", this_player())) { write ("You already have an account.\n") ; return 1 ; } if (this_player()->query("bank_balance")) { write ("Hm, you seem to have lost your card.. but you already have an account.\n"+"Let me give you a new card.\n") ; ob = clone_object(BANK_CARD_FILE) ; ob->assign(this_player()) ; return 1 ; } i = this_player()->query("wealth/gold") ; if (i<25) { write ("You need to have 25 gold coins to open an account.\n") ; return 1 ; } this_player()->set("wealth/gold",i-25) ; this_player()->set("capacity",this_player()->query("capacity")+25) ; ob = clone_object (BANK_CARD_FILE) ; ob -> assign(this_player()) ; write ("The banker hands you a shiny new bank card.\n"+ "You now have an account with First Mudwide Bank of TMI.\n") ; say (this_player()->query("cap_name")+" opens a bank account.\n") ; this_player()->set("bank_balance", ([ ]) ) ; return 1 ; } // Withdraw allows a player to withdraw money from his bank account. The // player must have his card to permit this. The function checks his card // to make sure he has enough money to make the withdrawal. // The bank knows about conversion: if the player wants to withdraw 5 gold // and has 0 gold and 50 silver in the bank, the bank withdraws his 50 silver // and gives him the 5 gold. More comments on this below. int withdraw (string str) { int number, i ; int oldval, newval, newnum ; string type, word, newtype ; object card, coins ; string *types ; if (!str) { notify_fail ("Usage: withdraw <number> <type>\n") ; return 0 ; } if (sscanf(str,"%d %s",number,type)!=2) { notify_fail ("Usage: withdraw <number> <type>\n") ; return 0 ; } if (number<1) { notify_fail ("You can only withdraw positive numbers of coins.\n") ; return 0 ; } card = present("bank card", this_player()) ; if (!card) { notify_fail ("You don't have an account!\n") ; return 0 ; } if ((int)card->query_val(type)>=number) { coins = clone_object(COINS) ; coins->set_number(number) ; coins->set_type(type) ; if (coins->move(this_player())==MOVE_OK) { if (number==1) word = "coin" ; else word="coins" ; write ("The banker hands you "+number+" "+type+" "+word+".\n") ; say (this_player()->query("cap_name")+" withdraws some "+type+".\n") ; card -> add_val (type,-number) ; return 1 ; } notify_fail ("You cannot carry that many more coins.\n") ; return 0 ; } // If the following lines (to the ending comment) are in place, if the player // can't withdraw what he requests, the bank will give him the same amount // of money in some other coinage if it can. For example, in the default // coin system, if he requests 20 gold but doesn't have that, the bank will // give him 2 platinum or 200 silver instead. This enables clever players // to change coinage for free. If you have a coin exchange which charges // a fee, you need to either rip this out, institute a fee on withdrawals, // or allow smart players to get a free ride... types = cointypes() ; i = member_array(type,types) ; if (i==-1) { notify_fail ("You don't have that many "+type+" and the bank cannot convert them.\n") ; return 0 ; } oldval = coinvalue(type) ; for (i=0;i<sizeof(types);i++) { newtype = types[i] ; newval = coinvalue(newtype) ; newnum = number*oldval/newval ; // Check to see if it's exact change. if ((number*oldval)-(newval*newnum)>0) continue ; // Check to see if he's got that many of the new type. if ((int)card->query_val(newtype)>=newnum) { coins = clone_object(COINS) ; coins->set_number(number) ; coins->set_type(type) ; if (coins->move(this_player())==MOVE_OK) { if (number==1) word = "coin" ; else word="coins" ; write ("You don't have that many "+type+" but you do have "+newnum+" "+newtype+".\n") ; write ("The banker withdraws "+newnum+" "+newtype+" from your account and hands you "+number+" "+type+" "+word+".\n") ; say (this_player()->query("cap_name")+" withdraws some "+type+".\n") ; card -> add_val (newtype,-newnum) ; return 1 ; } } } // Ending comment. If we get here, it means he didn't have enough of any // kind of coin to make his requested withdrawal. notify_fail ("You don't have enough coins of any type to withdraw that amount of money.\n") ; return 0 ; } // Deposit allows a player to put his money in the bank. int deposit(string str) { int i, number ; string type, word ; object card ; if (!str) { notify_fail("Usage: deposit <number> <type>\n") ; return 0 ; } if (sscanf(str,"%d %s",number,type)!=2) { notify_fail("Usage: deposit <number> <type>\n") ; return 0 ; } if (number<1) { notify_fail("You can only deposit positive numbers of coins.\n") ; return 0 ; } i = this_player()->query("wealth/"+type) ; if (i<number) { notify_fail ("You haven't got that many "+type+" to deposit.\n") ; return 0 ; } card = present("bank card",this_player()) ; if (!card) { notify_fail ("You'll need to open an account first.\n") ; return 0 ; } this_player()->set("wealth/"+type,i-number) ; this_player()->set("capacity",this_player()->query("capacity")+number) ; card->add_val(type,number) ; if (number==1) word="coin" ; else word="coins" ; write ("You deposit "+number+" "+type+" "+word+" in the bank.\n") ; say (this_player()->query("cap_name")+" deposits some "+type+".\n") ; return 1 ; }