tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
   This document explains how the various objects and commands in the
MudOS mudlib that deal with money and value work.

   The MudOS money system supports multiple coin types, and you can freely
create coins of any type you want, as long as each type is identified by
a unique string ("gold", "silver", etc.). This can be handy for quests or
other applications where you want a unique coin type to be available. 
   The amount of money a player has is stored in a property called "wealth."
Wealth is a mapping, where the keys are the types of coins and the values
are the amounts of each. Thus, the player's wealth might be:
	([ "gold" : 100, "silver" : 50 ])
if the player had 100 gold and 50 silver.
   You can find out how much of a particular coin type the player has by
calling query("wealth/<type>", eg query("wealth/gold") to find out how many
gold he has. You can find out what kinds of coins he has by creating a
mapping called foo, setting foo=query("wealth") and examining the keys
of foo. You can look at the score command to see how this is done.

   Piles of coins are clones of the standard object coins.c. When a player
drops coins, or when coins are given to an NPC, a copy of coins.c is cloned
and its two lfuns are called. These lfuns are set_type(), which sets the
type (gold, silver, etc.) and set_number() which sets the number of coins
in the pile. The coin's short description only reveals the type, and the
long description only reveals the approximate number. If the player picks
up the pile he can find out exactly how many are in it, or he can "count"
the pile. When a coin pile is moved to a new environment, it scans that
environment to see if another pile of the same type already exists. If it
does, the piles are merged. The encumbrance of a pile of coins is equal to
the number of coins in it. (This imposes the restriction that all coin types
weigh the same amount.) Coins.c defines the "money" property as a recognition
that the object is a pile of coins. Other objects should _not_ define this
property unless they also define query_type() and query_number(), and are
intended to be put into the player's purse rather than his inventory. (You
should not need to do this except for special cases, however.)
   The coin object redefines the move() function to handle two special
cases. The first of these is the presence of another pile of coins in
the destination of the same type. If a pile moves into a room containing
another pile, the incoming pile adds its number to the number of the
present pile and then deletes itself. This way, only one pile of coins of
each type will ever exist in a given room.
  Second, if the pile of coins is moving onto a player, we check to make
sure he can carry the pile. If not, we return an error message. If he can,
we add the coins to his wealth property, decrease his remaining capacity,
and destruct the object.
  The important point to get is that if you give a player money, you should
do so by cloning the coins object, setting the type and number, and moving
the coins onto the player. This will automatically take care of all the
weight checks, and the object will destruct itself if the move is successful.
When you take money away from a player, however, you should just decrease
the wealth property and increase the capacity yourself, since he can't
violate his weight restrictions this way. Examples of how to handle moving
money to and away from a player are found in the shop and bank, and in the
_get, _drop, and _give commands.
  In particular, you shouldn't try to use the scroll or other wiztool
to give yourself money: you don't want to try getting your encumbrance
and so forth set properly. What you should do instead is clone off a copy
of /obj/money_maker and use that to "vend" yourself some coins of your
favorite type. They will appear in your current environment, and when you pick
them up, all the property setting will be taken care of automatically. Be
careful not to let this tool fall into player hands, though...

   The relative value of different kinds of coins is controlled by a single
file called coinvalue.c. Coinvalue.c keeps two reference arrays: one a list
of the types of coins and the second an array of their relative values. The
least valuable coin has value 1; each other coin has value equal to the
number of least valuable coins for which it can be exchanged. The standard
coinvalue.c comes with four coin types: platinum, gold, silver, and copper.
Copper is the least valuable, having the value 1, and the other coins have
values 1000, 100, and 10 respectively. Thus, 1 platinum = 10 gold = 100
silver = 1000 copper. The standard object coinvalue.c has two lfuns, one of
which returns the list of types and the other returns the value of a specific
type. This file should be inherited by any object which may handle different
kinds of coins; ie. banks, shops.
   It is possible to have types of coins in the game which are not listed
with coinvalue.c. The only problem you will have is that these types of
coins cannot be converted into other kinds of coins, either to make change
or to make purchases. However, you can still use them for exact change
transactions. It is possible to have several different coinvalue.c files
each with a different list of convertable coins: for example, one exchange
might convert between gold and silver while another converted between
gold and platinum. However, you must make sure that two coins exchange at
exactly the same value in all versions of coinvalue.c, otherwise clever
players can create infinite amounts of money by buying low and selling
high at the two exchanges. The standard file exchange.c is an example
money exchange.

   The value of an object is controlled by the "value" property, which each
item should set in its create procedure. Objects which have no value property
or whose value is 0 cannot be sold in the standard shop. "value" is set to a
two element array, the first element being the number of coins and the second
being the type. For example, a sword worth 25 gold pieces should do this:
    set ("value", ({ 25, "gold" }) ) ;
The value of an object can be measured by calling query("value"), and
checking the appropriate array element.
   The file shop.c is an example shop. Each shop has its own local storeroom
which is a clone of the file storeroom.c, and also hooks up to a central
storeroom accessed by all shops. This reduces the number of objects you
need to have in storerooms: common objects like torches and swords should
be put in the common storeroom, which is the file warehouse.c. Warehouse.c
defines a list of objects to be cloned into the central storeroom at each
reset. In addition, to create variety each shop can also clone objects into
its own local storeroom. To create specialty shops, you can disconnect the
shop's access to the central storehouse and only access the local storeroom.
Objects that are sold to the shop are stored in the local storeroom; this 
means that they can only be bought from the store where they were sold.
   The shop sells objects for a different value than it buys them for.
The exact ration between the buy value and the sell value is stored in the
global constant SHOP_SELL_FRAC which is set in /include/money.h. It comes
set at 3/4 but you can set it to anything you want. If an object's value is
stated in a convertable coin other than the lowest one (copper as the mudlib
comes) then its sale value is calculated in the stated coin and some change
in the next lower coin. For example, a sword worth 10 gold pieces can be
sold to a shop for 7 gold pieces and 5 silver pieces. If the object's value
is stated in copper or in an unlisted coin, then it sells at 3/4 of its 
value in the stated coin (except that objects worth 1 copper do sell for
1 copper, and objects worth 1 sludge (or other non-listed coin) sell for
1 sludge.)
   The shop will accept coinage other than exact change for purchasing items.
Consider a player buying an object worth 35 gold pieces. First, the store
will check to see if the player has 35 gold. If he does not, it next checks
all higher-valued kinds of coins to see if the player can buy the object
with either of two combinations: higher coin plus the minumum number of
lower coin possible and higher coin plus all the player's lower coin. For
example, in the above case, if the player has 27 gold, the shop will sell
the sword if the player has 3 platinum and 5 gold, or if he has 1 platinum
and 25 gold. It will NOT check for 2 platinum and 15 gold: this is one of
two possibilities where a player may have enough coins to buy the object
but the store won't sell it to him.
   If none of the higher-valued coins make an exact change combination, the
shop next tries the coins lower in value than the coin in which the object's
value is stated. If the player has enough lower valued coins to make up his
shortfall in the stated coin, the shop will sell it to him. In the above
case, the shop will sell it to him for 27 gold and 80 silver, or for 27
gold and 800 copper.
   If the player cannot make exact change with lower-valued coins either,
then the shop will again try higher-valued coins, this time using only the
high-value coin and making change for the player. For example, if the player
has 0 gold but has 6 platinum, at this stage the shop will sell it to him
for 4 platinum and give him 5 gold in change.
   If none of these methods work, the store will conclude that the player
doesn't have enough money to buy the object. The other case in which this
is wrong is if the player has a combination of two coins, not the stated
coin, which enables him to buy the object. For example, the shop will not
accept 3 platinum and 50 silver in payment for the 35 gold piece sword. The
shop also will not detect combinations of three or more coins that would make
the necessary amount, for example 2 platinum, 10 gold, 40 silver, and 100
copper. Coders interested in extending the shop to handle these cases are
invited to drop by TMI and chat with Mobydick, but are warned that the
general solution to the problem is extremely difficult due to the large
number of possible combinations adding up to N of cointype X in a system
where the total number of coins is not predetermined.

   Banking services are provided by the files bank.c and bank_card.c. Bank.c
is a room which allows players to open bank accounts for a fee of 25 gold
coins (you can easily change this), in return for which they receive a bank
card. The bank also defines withdraw and deposit actions which allow players
to add and subtract money to/from their account. The amount of money each
player has is stored in the bank_card in the property "wealth" which is
exactly like the player object property; a mapping of coin types and amounts.
Thus, banks can also handle non-standard coins which are not listed in
coinvalue.c. The bank card is autoloading and preserves the player's balance
across logins. It also defines out the move procedure so that bank cards
cannot be dropped or given away except by the owning player. It defines
the balance command which shows the player his bank balance. This means that
the player can check his balance anywhere in the mud: if you wish to restrict
this so that balance can only be checked in the bank, take the balance
function out of bank_card.c and put it into bank.c.
   The bank will also handle the case of different coinages of equal value.
If the player wants to withdraw 50 gold, the bank will permit this if the
player has enough of any one type of coin in his account to match the amount,
ie he may withdraw 50 gold if he has 5 platinum, 50 gold, 500 silver, or
5000 copper. The bank as written will give the player 50 gold pieces regardless
of which coin is stored in his account, but you can easily alter the code so
that if he asks for 50 gold and has 5 platinum in his account he gets 
platinum coins instead of gold, if you so desire. The bank does not handle
the case of a player withdrawing 50 gold when he has 4 platinum and 100
silver in the bank. Again, people in extending the bank's flexibility are
invited to chat with Mobydick but the general solution is somewhat difficult.

   Clever players can use the shop and the bank to change coins. For example,
a player wishing to change 5 gold into silver can do this: deposit the 5
gold in the bank, withdraw all his silver from the bank, then withdraw 50
more silver from the bank. At the shop, he can drop his gold pieces, buy
an object worth 5 gold for 50 silver, then sell it back for 5 gold. Thus,
if you want to have the exchange charge a fee for changing coins, you need
to have the bank charge for withdrawals and have the shop sell for less than
full value, or you need to have the multi-coin features of the shop and bank
removed; otherwise your exchange will not get much use as players figure out
how to avoid paying the fee. The code for the shop and bank indicate which
lines need to be deleted to remove the multi-coin function.

   Comments and suggestions for improvement to Mobydick@TMI-2.