skylib_fluffos_v3/
skylib_fluffos_v3/bin/
skylib_fluffos_v3/bin/db/
skylib_fluffos_v3/fluffos-2.9-ds2.04/
skylib_fluffos_v3/fluffos-2.9-ds2.04/ChangeLog.old/
skylib_fluffos_v3/fluffos-2.9-ds2.04/Win32/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/simuls/
skylib_fluffos_v3/fluffos-2.9-ds2.04/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/clone/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/command/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/data/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/etc/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/master/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/log/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/compiler/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/efuns/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/operators/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/u/
skylib_fluffos_v3/fluffos-2.9-ds2.04/tmp/
skylib_fluffos_v3/fluffos-2.9-ds2.04/windows/
skylib_fluffos_v3/mudlib/
skylib_fluffos_v3/mudlib/cmds/
skylib_fluffos_v3/mudlib/cmds/admin/
skylib_fluffos_v3/mudlib/cmds/guild-race/
skylib_fluffos_v3/mudlib/cmds/living/broken/
skylib_fluffos_v3/mudlib/cmds/player/group_cmds/
skylib_fluffos_v3/mudlib/cmds/playtester/
skylib_fluffos_v3/mudlib/d/admin/
skylib_fluffos_v3/mudlib/d/admin/room/
skylib_fluffos_v3/mudlib/d/admin/room/we_care/
skylib_fluffos_v3/mudlib/d/admin/save/
skylib_fluffos_v3/mudlib/d/admin/text/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/buildings/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/map/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/roads/
skylib_fluffos_v3/mudlib/d/learning/chars/
skylib_fluffos_v3/mudlib/d/learning/functions/
skylib_fluffos_v3/mudlib/d/learning/handlers/
skylib_fluffos_v3/mudlib/d/learning/help_topics/
skylib_fluffos_v3/mudlib/d/learning/help_topics/npcs/
skylib_fluffos_v3/mudlib/d/learning/help_topics/objects/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/RCS/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/crowd/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/situations/
skylib_fluffos_v3/mudlib/d/learning/save/
skylib_fluffos_v3/mudlib/d/learning/school/
skylib_fluffos_v3/mudlib/d/learning/school/add_sc/
skylib_fluffos_v3/mudlib/d/learning/school/characters/
skylib_fluffos_v3/mudlib/d/learning/school/general/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/basic_commands/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/edtutor/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/unix_tutor/
skylib_fluffos_v3/mudlib/d/learning/school/items/
skylib_fluffos_v3/mudlib/d/learning/school/npc_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/room_basic/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/situations/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/terrain_tutor/
skylib_fluffos_v3/mudlib/d/learning/text/
skylib_fluffos_v3/mudlib/d/liaison/
skylib_fluffos_v3/mudlib/d/mudlib/
skylib_fluffos_v3/mudlib/d/mudlib/changes/
skylib_fluffos_v3/mudlib/d/playtesters/
skylib_fluffos_v3/mudlib/d/playtesters/effects/
skylib_fluffos_v3/mudlib/d/playtesters/handlers/
skylib_fluffos_v3/mudlib/d/playtesters/items/
skylib_fluffos_v3/mudlib/d/sage/
skylib_fluffos_v3/mudlib/doc/
skylib_fluffos_v3/mudlib/doc/creator/
skylib_fluffos_v3/mudlib/doc/driver/
skylib_fluffos_v3/mudlib/doc/driver/efuns/arrays/
skylib_fluffos_v3/mudlib/doc/driver/efuns/buffers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/calls/
skylib_fluffos_v3/mudlib/doc/driver/efuns/compile/
skylib_fluffos_v3/mudlib/doc/driver/efuns/filesystem/
skylib_fluffos_v3/mudlib/doc/driver/efuns/floats/
skylib_fluffos_v3/mudlib/doc/driver/efuns/functions/
skylib_fluffos_v3/mudlib/doc/driver/efuns/general/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mappings/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mixed/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mudlib/
skylib_fluffos_v3/mudlib/doc/driver/efuns/numbers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/parsing/
skylib_fluffos_v3/mudlib/doc/login/
skylib_fluffos_v3/mudlib/doc/lpc/basic_manual/
skylib_fluffos_v3/mudlib/doc/lpc/intermediate/
skylib_fluffos_v3/mudlib/doc/new/add_command/
skylib_fluffos_v3/mudlib/doc/new/events/
skylib_fluffos_v3/mudlib/doc/new/handlers/
skylib_fluffos_v3/mudlib/doc/new/living/race/
skylib_fluffos_v3/mudlib/doc/new/living/spells/
skylib_fluffos_v3/mudlib/doc/new/object/
skylib_fluffos_v3/mudlib/doc/new/player/
skylib_fluffos_v3/mudlib/doc/new/room/guild/
skylib_fluffos_v3/mudlib/doc/new/room/outside/
skylib_fluffos_v3/mudlib/doc/new/room/storeroom/
skylib_fluffos_v3/mudlib/doc/object/
skylib_fluffos_v3/mudlib/doc/playtesters/
skylib_fluffos_v3/mudlib/doc/policy/
skylib_fluffos_v3/mudlib/doc/weapons/
skylib_fluffos_v3/mudlib/global/
skylib_fluffos_v3/mudlib/global/creator/
skylib_fluffos_v3/mudlib/handlers/
skylib_fluffos_v3/mudlib/include/casino/
skylib_fluffos_v3/mudlib/include/cmds/
skylib_fluffos_v3/mudlib/include/effects/
skylib_fluffos_v3/mudlib/include/npc/
skylib_fluffos_v3/mudlib/include/room/
skylib_fluffos_v3/mudlib/include/shops/
skylib_fluffos_v3/mudlib/net/daemon/
skylib_fluffos_v3/mudlib/net/daemon/chars/
skylib_fluffos_v3/mudlib/net/inherit/
skylib_fluffos_v3/mudlib/net/obj/
skylib_fluffos_v3/mudlib/net/obj/BACKUPS/
skylib_fluffos_v3/mudlib/obj/amulets/
skylib_fluffos_v3/mudlib/obj/armours/plate/
skylib_fluffos_v3/mudlib/obj/b_day/
skylib_fluffos_v3/mudlib/obj/clothes/transport/horse/
skylib_fluffos_v3/mudlib/obj/faith/symbols/
skylib_fluffos_v3/mudlib/obj/fungi/
skylib_fluffos_v3/mudlib/obj/gatherables/
skylib_fluffos_v3/mudlib/obj/instruments/
skylib_fluffos_v3/mudlib/obj/media/
skylib_fluffos_v3/mudlib/obj/misc/player_shop/
skylib_fluffos_v3/mudlib/obj/monster/godmother/
skylib_fluffos_v3/mudlib/obj/monster/transport/
skylib_fluffos_v3/mudlib/obj/rings/
skylib_fluffos_v3/mudlib/obj/scabbards/
skylib_fluffos_v3/mudlib/obj/spells/
skylib_fluffos_v3/mudlib/obj/stationery/
skylib_fluffos_v3/mudlib/obj/stationery/envelopes/
skylib_fluffos_v3/mudlib/obj/toys/
skylib_fluffos_v3/mudlib/obj/vessels/
skylib_fluffos_v3/mudlib/obj/weapons/axes/
skylib_fluffos_v3/mudlib/obj/weapons/chains/
skylib_fluffos_v3/mudlib/obj/weapons/maces/BACKUPS/
skylib_fluffos_v3/mudlib/save/autodoc/
skylib_fluffos_v3/mudlib/save/book_handler/
skylib_fluffos_v3/mudlib/save/books/history/calarien/
skylib_fluffos_v3/mudlib/save/mail/
skylib_fluffos_v3/mudlib/save/new_soul/data/
skylib_fluffos_v3/mudlib/save/parcels/
skylib_fluffos_v3/mudlib/save/playerinfo/
skylib_fluffos_v3/mudlib/save/players/d/
skylib_fluffos_v3/mudlib/save/players/s/
skylib_fluffos_v3/mudlib/save/random_names/
skylib_fluffos_v3/mudlib/save/random_names/data/
skylib_fluffos_v3/mudlib/save/terrains/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_desert/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_grassy_field/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_mountain/
skylib_fluffos_v3/mudlib/save/todo_lists/
skylib_fluffos_v3/mudlib/secure/
skylib_fluffos_v3/mudlib/secure/cmds/admin/
skylib_fluffos_v3/mudlib/secure/cmds/lord/
skylib_fluffos_v3/mudlib/secure/config/
skylib_fluffos_v3/mudlib/secure/handlers/autodoc/
skylib_fluffos_v3/mudlib/secure/handlers/intermud/
skylib_fluffos_v3/mudlib/secure/include/global/
skylib_fluffos_v3/mudlib/secure/save/
skylib_fluffos_v3/mudlib/secure/save/handlers/
skylib_fluffos_v3/mudlib/secure/std/
skylib_fluffos_v3/mudlib/secure/std/classes/
skylib_fluffos_v3/mudlib/secure/std/modules/
skylib_fluffos_v3/mudlib/std/creator/
skylib_fluffos_v3/mudlib/std/dom/
skylib_fluffos_v3/mudlib/std/effects/
skylib_fluffos_v3/mudlib/std/effects/external/
skylib_fluffos_v3/mudlib/std/effects/fighting/
skylib_fluffos_v3/mudlib/std/effects/magic/
skylib_fluffos_v3/mudlib/std/effects/magic/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/other/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/priest/
skylib_fluffos_v3/mudlib/std/effects/room/
skylib_fluffos_v3/mudlib/std/environ/
skylib_fluffos_v3/mudlib/std/guilds/
skylib_fluffos_v3/mudlib/std/guilds/old/
skylib_fluffos_v3/mudlib/std/languages/
skylib_fluffos_v3/mudlib/std/liquids/
skylib_fluffos_v3/mudlib/std/npc/
skylib_fluffos_v3/mudlib/std/npc/goals/
skylib_fluffos_v3/mudlib/std/npc/goals/basic/
skylib_fluffos_v3/mudlib/std/npc/goals/misc/
skylib_fluffos_v3/mudlib/std/npc/plans/
skylib_fluffos_v3/mudlib/std/npc/plans/basic/
skylib_fluffos_v3/mudlib/std/npc/types/
skylib_fluffos_v3/mudlib/std/npc/types/helper/
skylib_fluffos_v3/mudlib/std/npcs/
skylib_fluffos_v3/mudlib/std/outsides/
skylib_fluffos_v3/mudlib/std/races/shadows/
skylib_fluffos_v3/mudlib/std/room/basic/BACKUPS/
skylib_fluffos_v3/mudlib/std/room/basic/topography/
skylib_fluffos_v3/mudlib/std/room/controller/
skylib_fluffos_v3/mudlib/std/room/inherit/topography/
skylib_fluffos_v3/mudlib/std/room/topography/area/
skylib_fluffos_v3/mudlib/std/room/topography/iroom/
skylib_fluffos_v3/mudlib/std/room/topography/milestone/
skylib_fluffos_v3/mudlib/std/shadows/curses/
skylib_fluffos_v3/mudlib/std/shadows/disease/
skylib_fluffos_v3/mudlib/std/shadows/fighting/
skylib_fluffos_v3/mudlib/std/shadows/healing/
skylib_fluffos_v3/mudlib/std/shadows/magic/
skylib_fluffos_v3/mudlib/std/shadows/poison/
skylib_fluffos_v3/mudlib/std/shadows/room/
skylib_fluffos_v3/mudlib/std/shops/controllers/
skylib_fluffos_v3/mudlib/std/shops/objs/
skylib_fluffos_v3/mudlib/std/shops/player_shop/
skylib_fluffos_v3/mudlib/std/socket/
skylib_fluffos_v3/mudlib/std/soul/d/
skylib_fluffos_v3/mudlib/std/soul/e/
skylib_fluffos_v3/mudlib/std/soul/i/
skylib_fluffos_v3/mudlib/std/soul/j/
skylib_fluffos_v3/mudlib/std/soul/k/
skylib_fluffos_v3/mudlib/std/soul/l/
skylib_fluffos_v3/mudlib/std/soul/n/
skylib_fluffos_v3/mudlib/std/soul/o/
skylib_fluffos_v3/mudlib/std/soul/q/
skylib_fluffos_v3/mudlib/std/soul/r/
skylib_fluffos_v3/mudlib/std/soul/u/
skylib_fluffos_v3/mudlib/std/soul/v/
skylib_fluffos_v3/mudlib/std/soul/y/
skylib_fluffos_v3/mudlib/std/soul/z/
skylib_fluffos_v3/mudlib/std/stationery/
skylib_fluffos_v3/mudlib/w/
skylib_fluffos_v3/mudlib/w/default/
skylib_fluffos_v3/mudlib/w/default/armour/
skylib_fluffos_v3/mudlib/w/default/clothes/
skylib_fluffos_v3/mudlib/w/default/item/
skylib_fluffos_v3/mudlib/w/default/npc/
skylib_fluffos_v3/mudlib/w/default/room/
skylib_fluffos_v3/mudlib/w/default/weapon/
skylib_fluffos_v3/mudlib/www/
skylib_fluffos_v3/mudlib/www/java/
skylib_fluffos_v3/mudlib/www/secure/
skylib_fluffos_v3/mudlib/www/secure/lpc/advanced/
skylib_fluffos_v3/mudlib/www/secure/lpc/intermediate/
skylib_fluffos_v3/win32/
#define __MONEY_CLASS__
#include <money.h>
#include <move_failures.h>
#include <obj_parser.h>

inherit OBJECT_OBJ;

private nosave int no_join;
private nosave int _already_joined;
private mixed money_array;
private nosave string _long;

void create() {
    ::create();
    set_name("coin");
    add_alias( MONEY_ALIAS );
    add_plural("coins");
    set_main_plural("coins");
    add_property("determinate", "");
    add_property("no one", 1 );
    add_property("money", 1 );
    money_array = ({ });
} /* create() */

/** @ignore yes */
int query_merger() { return 1; }

/** @ignore yes */
int query_no_join() { return no_join; }

/** @ignore yes */
int query_already_joined() { return _already_joined; }

/** @ignore yes */
void set_no_join() {
    no_join = 1;
    call_out("merge_coins", 0 );
} /* set_no_join() */

/** @ignore yes */
void reset_no_join() { no_join = 0; }

/**
 * This method returns the number of coins in the object.
 * @return the number of coins
 */
int query_number_coins() {
    int i, tot;

    if( _already_joined )
        return 0;

    for( i = 1; i < sizeof(money_array); i += 2 )
        tot += money_array[ i ];

    return tot;

} /* query_number_coins() */

/**
 * This method fixes up the weight of the money object to be what it should
 * be.
 */
void fixup_money_weight() {
    float total;
    int i;

    for( i = 0; i < sizeof(money_array); i += 2 )
        total += money_array[ i + 1 ] *
                 MONEY_H->query_weight_for( money_array[ i ] ) / 100.0;

    if( total < 1 )
        set_weight( 1 );
    else
        set_weight( to_int(total) );

} /* fixup_money_weight() */

/** @ignore yes */
int group_object() { return query_number_coins() > 1; }

/**
 * This method goes through the coins and sets up all the adjectives
 * and plurals it needs to.
 */
void check_adjectives() {
    int i;
    string *bits, *aliases;

    set_adjectives( ({ }) );
    set_aliases( ({ }) );
    set_plurals( ({ }) );

    if( !sizeof(money_array) ) {
        _already_joined = 0;
        move("/room/rubbish");
        _already_joined = 1;
        return;
    }

    add_alias(MONEY_ALIAS);

    for( i = 0; i < sizeof(money_array); i += 2 ) {
        aliases = MONEY_H->query_aliases_for( money_array[ i ] );
        bits = explode( lower_case( money_array[ i ] ), " ");

        if( sizeof(bits) > 1 ) {
            add_adjective( bits[0..<2] );
            if( sizeof( bits = explode( money_array[ i ], " ") - bits ) )
                add_adjective( bits );
        } else if( member_array( bits[0], aliases ) == -1 ) {
            add_adjective( bits[0] );
        }

        add_alias( aliases );
        add_plural( MONEY_H->query_plural_for( money_array[ i ] ) );

    }

    add_plural("coins");

} /* check_adjectives() */

/** @ignore yes */
mixed query_money_array() {
    return ( !_already_joined ? money_array : ({ }) );
} /* query_money_array() */

/** @ignore yes */
varargs int adjust_money( mixed amount, string type, int internal ) {
    int i, ret;

    if( pointerp( amount ) ) {
        for( i = 0; i < sizeof(amount); i += 2 )
            adjust_money( amount[ i + 1 ], amount[ i ], 1 );
        fixup_money_weight();
        return 1;
    }

    if( !stringp(type) || !intp(amount) || _already_joined )
        return 0;

    short_d = _long = 0;

    if( ( i = member_array( type, money_array ) ) == -1 ) {
        string *aliases, *bits;

        aliases = MONEY_H->query_aliases_for(type);
        bits = explode( lower_case( type ), " ");

        if( sizeof(bits) > 1 ) {
            add_adjective( bits[0..<2] );
            if( sizeof( bits = explode( type, " ") - bits ) )
                add_adjective( bits );
        } else if( member_array( bits[0], aliases ) == -1 ) {
            add_adjective( bits[0] );
        }

        add_alias( aliases );
        add_plural( lower_case( MONEY_H->query_plural_for(type) ) );
        money_array += ({ type, amount });
        ret = 1;

    } else {
        money_array[ i + 1 ] += amount;
        if( money_array[ i + 1 ] <= 0 ) {
            money_array = delete( money_array, i, 2 );
            if( find_call_out("check_adjectives") == -1 )
                call_out("check_adjectives", 0 );
            ret = 0;
        } else {
            ret = 1;
        }
    }

    if( !internal )
        fixup_money_weight();

    if( ret )
        return money_array[ i + 1 ];

    return 0;

} /* adjust_money() */

/** @ignore yes */
void set_money_array( mixed new_array ) {
    short_d = _long = 0;
    money_array = new_array;
    fixup_money_weight();

    if( find_call_out("check_adjectives") == -1 )
        call_out("check_adjectives", 0 );

} /* set_money_array() */

/** @ignore yes */
string *half_short( int full ) {
    int i;
    string *retval;

    retval = ({ });

    for( i = 0; i < sizeof(money_array); i += 2 ) {
        if( money_array[ i + 1 ] < 1 )
            continue;

        if( !full && ( money_array[ i + 1 ] > 12 ) ) {
            retval += ({ "some "+
                MONEY_H->query_main_plural_for( money_array[ i ] ) });
            continue;
        }

        if( money_array[ i + 1 ] == 1 ) {
            retval += ({ "one "+
                MONEY_H->query_short_for( money_array[ i ] ) });
            continue;
        }

        retval += ({ money_array[ i + 1 ] +" "+
                MONEY_H->query_main_plural_for( money_array[ i ] ) });

    }

    return retval;

} /* half_short() */

/** @ignore yes */
string short( int dark ) {
    string *retval;

    if( short_d )
        return short_d;

    retval = half_short( 0 );

    if( !sizeof( retval ) )
        return 0;

    if( sizeof( retval ) == 1 )
        short_d = retval[ 0 ];
    else
        short_d = query_multiple_short( retval );

    return short_d;

} /* short() */

/** @ignore yes */
string long( string word, int dark ) {
    int i;
    class money_data details;

    if( dark < -1 )
        return "It is too dark to see anything about the coins.\n";
    if( dark > 1 )
        return "It is too bright to see anything about the coins.\n";

    if( _long )
        return _long;

    if( !sizeof( money_array ) )
        return "This is some money that isn't money.\n";

    _long = "";

    for( i = 0; i < sizeof(money_array); i += 2 ) {
        details = MONEY_H->query_details_for( money_array[i] );
        _long += "Wrought from "+details->material+", the ";

        if( money_array[i+1] == 1 )
            _long += details->adj+" "+
                MONEY_H->query_short_for( money_array[i] )+" shows ";
        else
            _long += query_num( money_array[i+1] )+" "+details->adj+" "+
                MONEY_H->query_main_plural_for( money_array[i] )+" show ";

        _long += details->head_long+" on the reverse, and "+
                 details->tail_long+" on the obverse.\n";
    }

    return _long;

} /* long() */

/** @ignore yes */
string query_long_details( string word, int dark, object looker ) {
    if( dark < -1 )
        return "It is too dark to see anything about the coins.\n";
    if( dark > 1 )
        return "It is too bright to see anything about the coins.\n";
    return long( word, dark );
} /* query_long_details() */

/**
 * This method creates a new money object from the current object.  It uses
 * the current objects values to make the money and removes the values from
 * the coins.
 * @param number the number of coins to remove
 * @param type the type of coins to remove
 * @return the new money object
 */
private object new_money_object( int number, string type, object money ) {
    int i;

    if( !sizeof( money_array ) || _already_joined )
        return 0;

    if( !type || type == "" )
        return 0;

    if( ( i = member_array( type, money_array ) ) == -1 )
        return 0;

    if( number > money_array[ i + 1 ] )
        return 0;

    if( !money )
        money = clone_object(MONEY_OBJ);

    money->set_no_join();

    short_d = _long = 0;

    // First we need to remove stuff from our array and update the weight,
    // because otherwise add_weight() will not work in our container.
    // If we adjust the weight of the newly created object first, we will
    // end up with broken local weights in containers.
    // This only happens with full containers or burdened players.
    // - Sandoz.
    money_array[ i + 1 ] -= number;
    fixup_money_weight();

    // This fixes up the weight of the new object as well.
    money->adjust_money( number, type );

    // Only now we try to move it, if it fails, move it to our room.
    // This should help prevent broken local weights as well.
    if( money->move( environment() ) ) {
        object env, who;

        if( env = ENV( who = environment() ) ) {
            object tmp;

            // Let's move us to the room, and give a message to
            // the player whose inventory we are in.
            while( tmp = ENV( env ) ) {
                if( interactive(env) )
                    who = env;
                env = tmp;
            }

            money->move(env);

            tell_object( who, "Oh dear, "+money->the_short()+" refuse to fit "
                "in "+environment()->the_short()+" any more and find their "
                "way to "+env->the_short()+".\n");
        }
    }

    if( money_array[ i + 1 ] < 1 ) {
        // Remove the adjective right away so that we won't match on it again.
        remove_adjective( money_array[ i ] );
        money_array = delete( money_array, i, 2 );
        if( find_call_out("check_adjectives") == -1 )
            call_out("check_adjectives", 0 );
    }

    return money;

} /* new_money_object() */

/**
 * This method merges two coin object together.  Or attempts to anyway.
 * This will occur whenever a coin object moves.
 * @return the merged coin object
 */
object merge_coins() {
    object money;

    remove_alias(MONEY_ALIAS);

    if( environment() )
        money = present( MONEY_ALIAS, environment() );

    if( objectp( money ) && money != TO && !_already_joined ) {
        // First move us to the rubbish room to update the local weight of the
        // container, then adjust the money array on the target money object.
        // Otherwise we may end up with bad local weights again.
        // - Sandoz.
        set_no_join();
        move("/room/rubbish");
        _already_joined = 1;
        money->adjust_money( money_array );
        return money;
    } else {
        add_alias( MONEY_ALIAS );
    }

    return TO;

} /* merge_coins() */

/** @ignore yes */
varargs int move( mixed dest, string messin, string messout ) {
    int i;

    if( _already_joined )
        return MOVE_INVALID_DEST;

    i = ::move( dest, messin, messout );
    if( i != MOVE_OK )
        return i;

    if( file_name( environment() ) == "/room/rubbish" || no_join )
        reset_no_join();
    else
        merge_coins();

    return MOVE_OK;

} /* move() */

/** @ignore yes */
public varargs mixed find_best_fit( mixed word, int flag ) {
    int i, best, best_rating, rating;
    string against, *words, *arr;

    if( !word || word == "")
        return 0;

    if( stringp(word) )
        words = explode( lower_case( word ), " ") - ({"coin", "coins"});
    else
        words = word;

    if( flag )
        arr = ({ });

    best = -1;

    for( i = 0; i < sizeof( money_array ); i += 2 ) {
        rating = 0;
        against = "X "+lower_case( replace( money_array[ i ] +" "+
            MONEY_H->query_plural_for( money_array[ i ] ), " coins", "") )+" X";

        foreach( word in words ) {
            if( sscanf( against, "%*s "+lower_case(word)+" %*s") == 2 )
                rating++;
        }

        if( flag && rating >= best_rating )
            arr += ({ money_array[i] });

        if( rating > best_rating ) {
            best_rating = rating;
            best = i;
            if( flag )
                arr = ({ money_array[i] });
        }
    }

    if( flag )
        return arr;

    return best;

} /* find_best_fit() */

/** @ignore yes */
object query_parse_id( mixed arr ) {
    int i;
    string *bits;
    object money;

    if( arr[ 0 ] < 0 || !sizeof( money_array ) )
        return 0;

    if( arr[ 0 ] == 0 ) {
        bits = explode( arr[ 1 ], " ");

        if( sizeof(bits) == 1 && bits[ 0 ] == "coins")
            return TO;

        if( member_array( bits[<1], query_plurals() ) == -1 )
            return TO;

        if( ( i = find_best_fit( arr[ 1 ] ) ) == -1 )
            return 0;

        money = new_money_object( money_array[ i + 1 ], money_array[ i ], 0 );
        return money;

    }

    // Not very satisfactory.
    if( ( i = find_best_fit( arr[ 1 ] ) ) == -1 )
        i = 0;

    if( arr[ 0 ] > money_array[ i + 1 ] )
        return 0;

    money = new_money_object( arr[ 0 ], money_array[ i ], 0 );
    return money;

} /* query_parse_id() */

/** @ignore yes */
mixed parse_match_object( string *input, object viewer,
                          class obj_match_context context ) {
    int ret, num, every;
    mixed found;
    object ob;

    if( !sizeof(money_array) )
        return 0;

    if( !ret = ::is_matching_object( input, viewer, context ) )
        return 0;

    if( sizeof(input) == 1 && !context->number_included && !context->ordinal ) {
        if( input[<1] == "coins" || input[<1] == "money" || input[<1] == "all")
            return ({ OBJ_PARSER_MATCH_PLURAL, ({ TO }) });
        if( input[<1] == "coin") {
            // Only one coin.
            if( sizeof( money_array ) == 2 && money_array[ 1 ] == 1 )
                return ({ OBJ_PARSER_MATCH_PLURAL, ({ TO }) });
            // Pick the first coin, any coin...
            if( !num = update_parse_match_context( context, 1, ret ) )
                return 0;
            if( !ob = new_money_object( num, money_array[ 0 ], 0 ) )
                return 0;
            return ({ ret, ({ ob }) });
        }
    }

    every = context->number_included == EVERY_NUM;

    if( sizeof(input) == 1 && input[<1] == "coin") {
        // We matched on "every coin".
        if( every )
            return ({ ret, ({ TO }) });
        // Make it the first random coin.
        input[<1] = money_array[ 0 ];
    }

    if( every || ( !context->number_included && input[<1] == "coins") ) {
        if( sizeof( found = find_best_fit( input, 1 ) ) ) {
            foreach( string str in found ) {
                int i;

                // Lets see how many we have...
                i = member_array( str, money_array );
                num = money_array[ i + 1 ];
                if( num = update_parse_match_context( context, num, ret ) ) {
                    ob = new_money_object( num, str, ob );
                    // Do this so that we keep matching on the rest as well.
                    if( every )
                        context->number_included = EVERY_NUM;
                }
            }
        }

        if( ob )
            return ({ ret, ({ ob }) });
    }

    if( ( found = find_best_fit(input) ) == -1 )
        return 0;

    // Lets see how many we have...
    num = money_array[ found + 1 ];
    if( !num = update_parse_match_context( context, num, ret ) )
        return 0;

    if( !ob = new_money_object( num, money_array[found], 0 ) )
        return 0;

    return ({ ret, ({ ob }) });

} /* parse_match_object() */

/** @ignore yes */
int do_not_sell() { return 1; }

/** @ignore yes */
int query_value() { return 0; }

/** @ignore yes */
int query_value_in( string where ) {
    return MONEY_H->query_total_value( money_array, where );
} /* query_value_in() */

/**
 * This method returns the amount of type of money there is in the array.
 * @param type the type of money to check
 * @return the number of coins of that type
 */
int query_money( string type ){
    int i;

    if( ( i = member_array( type, money_array ) ) == -1 )
        return 0;

    return money_array[i+1];

} /* query_money () */

/** @ignore yes */
mapping query_dynamic_auto_load() {
    if( !_already_joined ) {
        return ([
            "::" : ::query_dynamic_auto_load(),
            "money array" : money_array,
        ]);
    }
} /* query_dynamic_auto_load() */

/** @ignore yes */
void init_dynamic_arg( mapping map ) {
    ::init_dynamic_arg( map["::"] );
    set_money_array( map["money array"] );
} /* init_dynamic_arg() */