dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/*
** The way this used to be, if the player trying to work the quest 
** suddenly buggered off in the middle of it, the quest related 
** weights would still be there, but if another player came along and 
** moved one of the weights, the quest related one would vanish. This 
** has puzzled players, and cased at least one bug report.  I've changed 
** it so that the quest related weight hangs around until a player resets 
** the weights or actually starts the quest using the figure command. 
**
** Also removed some code that has been commented out for two years, and 
** some other bits that were redundant because of this piece of unused 
** code. And did some general Spring Cleaning. It seems to be working fine, 
** but feel free to revert it if it breaks horribly.  --Tilly  
*/ 


#include <library.h>

#define DEFAULT_PANS ([ \
  "left" : ([ ]), \
  "middle" : ([ \
  "very small" : ({ "1/9", 1 }), \
  "small" : ({ "1/3", 3 }), \
  "medium" : ({ "1", 9 }), \
  "large" : ({ "3", 27 }), \
  "very large" : ({ "9", 81 }) ]), \
  "right" : ([ ]) ])

inherit "/std/object";

private nosave int balance;
private nosave string *doing;
private nosave mapping pans;


/* Start of function prototypes */
void setup();
void init();
string *query_doing();
mapping query_pans();
string long( string words, int dark );
string pans_look();
void recalculate_balance();
int reset_weights();
string weight_string( int weight );
int weigh_something( object* obs );
int figure_it_out();
int move_a_specific_weight( string weight_size, string pan_to );
int move_a_weight( string weight_size, string pan_from, string pan_to );
void it_is_balanced( object person );
/* End of function prototypes */


void setup() {
  set_name( "balance" );
  set_short( "weighing balance" );
  add_adjective( "weighing" );
  add_alias( ({ "pan", "pans", "weight", "weights" }) );
  set_weight( 200 );
  reset_get();
  doing = ({ });
  pans = DEFAULT_PANS;
} /* setup() */


void init() {
  add_command("weigh", "<indirect:object:me'thing(s)'> on <direct:object>",
    (:this_object()->weigh_something($1):));
  add_command("reset", "weights on balance", (: reset_weights() :));
  add_command("figure", "", (:this_object()->figure_it_out():));
  add_command("move",
          "<string'size'> weight to <string'position'> pan",
          (:this_object()->move_a_specific_weight($4[0], $4[1]):));
} /* init() */


string *query_doing() { return doing; }

mapping query_pans() { return pans; }


string long( string words, int dark ) {
  int i, j;
  string long;
  string *bits;
  string *places;
  string *weights;

  if (!words) {
    words = "balance";
  }
  bits = explode( words, " " );
  switch ( bits[ sizeof( bits ) - 1 ] ) {
    case "balance" :
      return "This is a largish bronze balance, securely bolted in "
        "place.  The main part of the balance is a long arm which "
        "pivots at its centre.  There is a pan hanging from each "
        "end of the arm such that it will be level when the weights "
        "in the pans are equal.  A third pan is fixed to a stationary "
        "part of the balance where the weights can be held when not "
        "in use.\n" + pans_look() + "You could probably use the balance "
        "to weigh something.\nThere appears to be something "
        "written on it.\n";
    case "pan" :
    case "pans" :
      return "There are three pans.  One pan hangs from the left end of "
        "the arm, one from the right end and there is a third pan "
        "in the middle.\n"+ pans_look();
    case "weight" :
    case "weights" :
      long = "There are weights of many different sizes in the pans.  "
        "They are:\n";
      bits = ({ });
      places = m_indices( pans );
      for ( i = 0; i < sizeof( places ); i++ ) {
        if ( !m_sizeof( pans[ places[ i ] ] ) ) {
          continue;
        }
        weights = m_indices( pans[ places[ i ] ] );
        for ( j = 0; j < sizeof( weights ); j++ ) {
          if ( sizeof( doing ) ) {
            if ( doing[ 1 ] == weights[ j ] ) {
              continue;
            }
          }
          bits += ({ add_a( weights[ j ] ) + " weight marked with \""
            + pans[ places[ i ] ][ weights[ j ] ][ 0 ] +" lb\"" });
        }
      }
      long += "    " + implode( bits[ 0 .. sizeof( bits ) - 2 ],
        ",\n    " ) +",\n  and "+ bits[ sizeof( bits ) - 1 ] + ".\n";
      long += "The weights can be moved from one pan to another and "
        "reset back to their starting positions.\n";
      return long;
  }
  return "You're not quite sure what you're looking at.\n";
} /* long() */


string pans_look() {
  int i;
  int j;
  string pans_status;
  string *places;
  string *weights;

  pans_status = "";
  places = m_indices( pans );
  for ( i = 0; i < sizeof( places ); i++ ) {
    pans_status += "The "+ places[ i ] +" pan ";
    if ( !m_sizeof( pans[ places[ i ] ] ) )
      pans_status += "is empty.\n";
    else {
      weights = m_indices( pans[ places[ i ] ] );
      for ( j = 0; j < sizeof( weights ); j++ )
        weights[ j ] = add_a( weights[ j ] ) +" weight";
      pans_status += "holds "+ query_multiple_short( weights ) +".\n";
    }
  }
  switch ( balance ) {
    case -1 :
      pans_status += "The left pan hangs lower than the right pan.\n";
      break;
    case 0 :
      pans_status += "The left pan hangs level with the right pan.\n";
      break;
    case 1 :
      pans_status += "The left pan hangs higher than the right pan.\n";
      break;
  }
  return pans_status;
} /* pans_look() */


void recalculate_balance() {
  int i;
  int j;
  int old_balance;
  string *places;
  string *weights;
  mapping pan_weights;

  pan_weights = ([ ]);
  places = m_indices( pans );
  for ( i = 0; i < sizeof( places ); i++ ) {
    pan_weights[ places[ i ] ] = 0;
    if ( !m_sizeof( pans[ places[ i ] ] ) ) {
      continue;
    }
    weights = m_indices( pans[ places[ i ] ] );
    for ( j = 0; j < sizeof( weights ); j++ ) {
      pan_weights[ places[ i ] ] +=
        pans[ places[ i ] ][ weights[ j ] ][ 1 ];
    }
  }
  old_balance = balance;
  if ( pan_weights[ "left" ] > pan_weights[ "right" ] ) {
    balance = -1;
  } else {
    if ( pan_weights[ "left" ] == pan_weights[ "right" ] ) {
      balance = 0;
    } else {
      balance = 1;
    }
  }
  if ( old_balance == balance ) {
    switch ( balance ) {
      case -1 :
        tell_room( environment(), "The arm rocks a bit but steadies, "
          "with the left pan still hanging lowest.\n" );
        break;
      case 1 :
        tell_room( environment(), "The arm rocks a bit but steadies, "
          "with the right pan still hanging lowest.\n" );
        break;
    }
    return;
  }
  switch ( balance ) {
    case -1 :
      tell_room( environment(), "The arm of the balance tips and the "
        "left pan ends up hanging lowest.\n" );
      break;
    case 0 :
      tell_room( environment(), "The arm of the balance levels out, "
        "with the left and right pans hanging level.\n" );
      break;
    case 1 :
      tell_room( environment(), "The arm of the balance tips and the "
        "right pan ends up hanging lowest.\n" );
      break;
  }
} /* recalculate_balance() */


int reset_weights() {
  pans = DEFAULT_PANS;
  if (sizeof(doing)) {
    pans[ "left" ][ doing[ 1 ] ] = ({ "?", 1 + random( 121 ) });
  }
  add_succeeded_mess("$N $V the weights on $D.\n");
  recalculate_balance();
  return 1;
} /* reset_weights() */


string weight_string( int weight ) {
  int wholes;
  int ninths;

  wholes = weight / 9;
  ninths = weight % 9;
  if ( wholes && ninths ) {
    return wholes + " " + ninths + "/9 lb";
  }
  if ( wholes ) {
    return wholes + " lb";
  }
  return ninths + "/9 lb";
} /* weight_string() */


int weigh_something( object* obs ) {
  int i;
  int info;
  int weight;
  object person;

  if ( sizeof( doing ) ) {
    person = find_player( doing[ 0 ] );
    if ( person == this_player() ) {
      add_failed_mess( "Hold your horses, you're trying to get the hang "
        "of it still.\n" );
      return 0;
    }
    if ( person && ( environment( person ) == environment() ) ) {
      add_failed_mess( (string)person->one_short() + " is using "
        "the balance at the moment.  Come back when "
        + (string)person->query_pronoun() + " has finished.\n" );
      return 0;
    }
    doing = ({ });
    pans = DEFAULT_PANS;
  }
  info = (int)LIBRARY->query_player_quest_info(
    (string)this_player()->query_name(), "balance" );
  switch ( info ) {
    case 0 :
      add_failed_mess( "You don't know how the balance works to weigh "
        "anything.\nTry looking at the balance, the pans and "
        "the weights, and then maybe you can figure it out.\n" );
      return 0;
    case 1 :
      add_failed_mess( "You're still not too sure how the balance works "
        "to weigh anything.\nTry looking at the balance, the pans and "
        "the weights, and then maybe you can figure it out.\n" );
      return 0;
    case 2 :
      add_failed_mess( "You're very nearly sure how the balance works, "
        "but maybe you should try to figure it out once more before "
        "you weigh anything.\n" );
      return 0;
  }
  for ( i = 0; i < sizeof( obs ); i++ ) {
    weight = obs[ i ]->query_complete_weight();
    if ( !weight ) {
      write( obs[ i ]->the_short() + " doesn't weigh anything.\n" );
      continue;
    }
    if ( weight > 121 ) {
      write( obs[ i ]->the_short() +
        " is heavier than all the weights available put together.\n" );
      continue;
    }
    write( obs[ i ]->the_short() +
      " weighs "+ weight_string( weight ) +".\n" );
  }
  add_succeeded_mess(({ "", "$N $V $I on $D.\n" }), obs);
  return 1;
} /* weigh_something() */


int figure_it_out() {
  int info;
  object person;

  if ( sizeof( doing ) ) {
    person = find_player( doing[ 0 ] );
    if ( person == this_player() ) {
      notify_fail( "You're already engaged in figuring out how the "
        "balance can be used to weigh something.\n" );
      return 0;
    }
    if ( person && ( environment( person ) == environment() ) ) {
      notify_fail( (string)person->one_short() + " is using "
        "the balance at the moment.  Come back when "
        + (string)person->query_pronoun() + " has finished.\n" );
      return 0;
    }
    doing = ({ });
    pans = DEFAULT_PANS;
  }
  info = (int)LIBRARY->query_player_quest_info(
    (string)this_player()->query_name(), "balance" );
  if ( info > 2 ) {
    write( "You already know how the balance works.\n" );
    return 1;
  }
  doing = ({ (string)this_player()->query_name(), ({ "red", "green",
    "blue" })[ info ] });
  write( "You see " + add_a( doing[ 1 ] ) + " weight in the middle pan "
    "that you hadn't noticed before.  Maybe you could use this to "
    "experiment, so you place it in the left pan.\n" );
  say( (string)this_player()->one_short() + " moves "
    + add_a( doing[ 1 ] ) + " weight from the middle pan to the "
    "left pan.\n" );
  pans[ "left" ][ doing[ 1 ] ] = ({ "?", 1 + random( 121 ) });
  recalculate_balance();
  return 1;
} /* figure_it_out() */


int move_a_specific_weight( string weight_size, string pan_to ) {
  object person;
  string pan_from;

  if ( sizeof( doing ) ) {
    person = find_player( doing[ 0 ] );
    if ( !person ) {
      doing = ({ });
    } else {
      if ( person != this_player() ) {
        if ( environment( person ) == environment() ) {
          add_failed_mess( (string)person->one_short() + " is "
            "using the balance at the moment.  Come back when "
            + (string)person->query_pronoun() + " has finished.\n" );
          return 0;
        } else {
          doing = ({ });
          pans = DEFAULT_PANS;
        }
      }
    }
  }

  if ( !pans[ pan_to ] ) {
    add_failed_mess( "There is a left pan, a middle pan and a right pan, "
      "but no " + pan_to + " pan.\n" );
    return 0;
  }
  foreach (pan_from in keys(pans)) {
    if ( pans[ pan_from ][ weight_size ] ) {
      return move_a_weight(weight_size, pan_from, pan_to);
    }
  }
  add_failed_mess("Unable to find the " + weight_size + " weight.\n");
  return 0;
} /* move_a_specific_weight() */


int move_a_weight( string weight_size, string pan_from, string pan_to ) {

  if ( pan_from == pan_to ) {
    add_failed_mess( "The " + weight_size + " weight is already in the "
      + pan_to + " pan.\n" );
    return 0;
  }
  if ( sizeof( doing ) ) {
    if ( weight_size == doing[ 1 ] ) {
      notify_fail( "You don't feel like moving the " + doing[ 1 ]
        + " weight since that's what you're trying to weigh.\n" );
      return 0;
    }
  }
  pans[ pan_to ][ weight_size ] = pans[ pan_from ][ weight_size ];
  pans[ pan_from ] = m_delete( pans[ pan_from ], weight_size );
  write( "You move the "+ weight_size +" weight from the "+ pan_from
    + " pan to the "+ pan_to + " pan.\n" );
  say( (string)this_player()->one_short() + " moves "
    + add_a( weight_size ) +" weight from the "+ pan_from + " pan "
    "of the balance to the " + pan_to + " pan.\n" );
  recalculate_balance();
  if ( sizeof( doing ) && !balance ) {
    call_out( "it_is_balanced", 0, this_player() );
  }
  return 1;
} /* move_a_weight() */


void it_is_balanced( object person ) {
  int info;

  tell_object( person, "You feel a small surge of self-esteem to have found "
    "that the "+ doing[ 1 ] +" weight weighs "
    + weight_string( pans[ "left" ][ doing[ 1 ] ][ 1 ] ) +".\n" );
  info = (int)LIBRARY->query_player_quest_info( (string)person->query_name(),
    "balance" );
  info++;
  switch ( info ) {
    case 1 :
      tell_object( person, "You've made a good start at working out "
        "how the balance operates.  You think you should practice "
        "with it a couple of times more to get the hang of it, "
        "though.\n" );
      person->adjust_xp( 5000 );
      break;
    case 2 :
      tell_object( person, "You're definitely getting to understand how "
        "the balance operates.  You think you should practice with "
        "it once more to get used to it completely, though.\n" );
      person->adjust_xp( 10000 );
      break;
    case 3 :
      tell_object( person, "You're now adept at using the balance and "
        "can use it to weigh anything.\n" );
/* Quest!
 * Name: balance quest
 * Title: Expert Balancer
 * Story: discovered how to weigh things using powers of three
 * Level: 3
 */
      if ( interactive( person ) ) {
        if ( !LIBRARY->query_quest_done( (string)person->query_name(),
          "balance quest" ) ) {
          LIBRARY->set_quest( (string)person->query_name(),
            "balance quest" );
        }
      }
      break;
    case 4:
      info--;
      break; //if people want to keep moving the weights, let them.
    default :
      tell_object( person, "Something has gone wrong with the balance.  "
        "Please contact Wodan about it.\n" );
  }
  LIBRARY->set_player_quest_info( (string)person->query_name(), "balance",
    info );
  tell_object( person, "You put all the weights back into the middle "
    "pan.\n" );
  tell_room( environment(), (string)person->the_short() +
     " seems satisfied with "+ (string)person->query_objective() +"self, "
    "and returns all of the weights to the middle pan.\n", person );
  doing = ({ });
  pans = DEFAULT_PANS;
} /* it_is_balanced() */