dw_fluffos_v1/
dw_fluffos_v1/fluffos-1.22c11/
dw_fluffos_v1/fluffos-1.22c11/ChangeLog.old/
dw_fluffos_v1/fluffos-1.22c11/Win32/
dw_fluffos_v1/fluffos-1.22c11/compat/
dw_fluffos_v1/fluffos-1.22c11/compat/simuls/
dw_fluffos_v1/fluffos-1.22c11/include/
dw_fluffos_v1/fluffos-1.22c11/mudlib/
dw_fluffos_v1/fluffos-1.22c11/testsuite/
dw_fluffos_v1/fluffos-1.22c11/testsuite/clone/
dw_fluffos_v1/fluffos-1.22c11/testsuite/command/
dw_fluffos_v1/fluffos-1.22c11/testsuite/data/
dw_fluffos_v1/fluffos-1.22c11/testsuite/etc/
dw_fluffos_v1/fluffos-1.22c11/testsuite/include/
dw_fluffos_v1/fluffos-1.22c11/testsuite/inherit/
dw_fluffos_v1/fluffos-1.22c11/testsuite/inherit/master/
dw_fluffos_v1/fluffos-1.22c11/testsuite/log/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/tests/compiler/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/tests/efuns/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/tests/operators/
dw_fluffos_v1/fluffos-1.22c11/testsuite/u/
dw_fluffos_v1/fluffos-1.22c11/tmp/
dw_fluffos_v1/lib/
dw_fluffos_v1/lib/binaries/cmds/
dw_fluffos_v1/lib/binaries/cmds/creator/
dw_fluffos_v1/lib/binaries/cmds/living/
dw_fluffos_v1/lib/binaries/cmds/player/
dw_fluffos_v1/lib/binaries/d/admin/obj/
dw_fluffos_v1/lib/binaries/d/liaison/
dw_fluffos_v1/lib/binaries/global/virtual/
dw_fluffos_v1/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v1/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v1/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v1/lib/binaries/obj/misc/
dw_fluffos_v1/lib/binaries/obj/misc/buckets/
dw_fluffos_v1/lib/binaries/obj/monster/
dw_fluffos_v1/lib/binaries/obj/reactions/
dw_fluffos_v1/lib/binaries/obj/reagents/
dw_fluffos_v1/lib/binaries/secure/cmds/creator/
dw_fluffos_v1/lib/binaries/secure/master/
dw_fluffos_v1/lib/binaries/std/
dw_fluffos_v1/lib/binaries/std/dom/
dw_fluffos_v1/lib/binaries/std/effects/object/
dw_fluffos_v1/lib/binaries/std/guilds/
dw_fluffos_v1/lib/binaries/std/languages/
dw_fluffos_v1/lib/binaries/std/races/
dw_fluffos_v1/lib/binaries/std/room/
dw_fluffos_v1/lib/binaries/std/room/basic/
dw_fluffos_v1/lib/binaries/std/shops/
dw_fluffos_v1/lib/binaries/std/shops/inherit/
dw_fluffos_v1/lib/binaries/www/
dw_fluffos_v1/lib/cmds/guild-race/
dw_fluffos_v1/lib/cmds/guild-race/crafts/
dw_fluffos_v1/lib/cmds/guild-race/other/
dw_fluffos_v1/lib/cmds/playtester/
dw_fluffos_v1/lib/cmds/playtester/senior/
dw_fluffos_v1/lib/d/admin/
dw_fluffos_v1/lib/d/admin/log/
dw_fluffos_v1/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v1/lib/d/admin/meetings/
dw_fluffos_v1/lib/d/admin/obj/
dw_fluffos_v1/lib/d/admin/room/we_care/
dw_fluffos_v1/lib/d/admin/save/
dw_fluffos_v1/lib/d/dist/
dw_fluffos_v1/lib/d/dist/mtf/
dw_fluffos_v1/lib/d/dist/pumpkin/
dw_fluffos_v1/lib/d/dist/pumpkin/chars/
dw_fluffos_v1/lib/d/dist/pumpkin/desert/
dw_fluffos_v1/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v1/lib/d/dist/pumpkin/hospital/
dw_fluffos_v1/lib/d/dist/pumpkin/inherit/
dw_fluffos_v1/lib/d/dist/pumpkin/map/
dw_fluffos_v1/lib/d/dist/pumpkin/plain/
dw_fluffos_v1/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v1/lib/d/dist/pumpkin/save/
dw_fluffos_v1/lib/d/dist/pumpkin/squash/
dw_fluffos_v1/lib/d/dist/pumpkin/terrain/
dw_fluffos_v1/lib/d/dist/pumpkin/woods/
dw_fluffos_v1/lib/d/dist/start/
dw_fluffos_v1/lib/d/learning/TinyTown/buildings/
dw_fluffos_v1/lib/d/learning/TinyTown/map/
dw_fluffos_v1/lib/d/learning/TinyTown/roads/
dw_fluffos_v1/lib/d/learning/add_command/
dw_fluffos_v1/lib/d/learning/arms_and_weps/
dw_fluffos_v1/lib/d/learning/chars/
dw_fluffos_v1/lib/d/learning/cutnpaste/
dw_fluffos_v1/lib/d/learning/examples/npcs/
dw_fluffos_v1/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v1/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v1/lib/d/learning/functions/
dw_fluffos_v1/lib/d/learning/handlers/
dw_fluffos_v1/lib/d/learning/help_topics/npcs/
dw_fluffos_v1/lib/d/learning/help_topics/objects/
dw_fluffos_v1/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v1/lib/d/learning/help_topics/rooms/
dw_fluffos_v1/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v1/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v1/lib/d/learning/items/
dw_fluffos_v1/lib/d/learning/save/
dw_fluffos_v1/lib/d/liaison/
dw_fluffos_v1/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v1/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v1/lib/db/
dw_fluffos_v1/lib/doc/
dw_fluffos_v1/lib/doc/creator/
dw_fluffos_v1/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v1/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v1/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v1/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v1/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v1/lib/doc/creator/autodoc/std/key/
dw_fluffos_v1/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v1/lib/doc/creator/autodoc/std/map/
dw_fluffos_v1/lib/doc/creator/autodoc/std/race/
dw_fluffos_v1/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v1/lib/doc/creator/files/
dw_fluffos_v1/lib/doc/creator/policy/
dw_fluffos_v1/lib/doc/creator/room/
dw_fluffos_v1/lib/doc/effects/
dw_fluffos_v1/lib/doc/ideas/
dw_fluffos_v1/lib/doc/known_command/
dw_fluffos_v1/lib/doc/lpc/basic_manual/
dw_fluffos_v1/lib/doc/lpc/intermediate/
dw_fluffos_v1/lib/doc/new/add_command/
dw_fluffos_v1/lib/doc/new/handlers/
dw_fluffos_v1/lib/doc/new/living/
dw_fluffos_v1/lib/doc/new/living/race/
dw_fluffos_v1/lib/doc/new/living/spells/
dw_fluffos_v1/lib/doc/new/player/
dw_fluffos_v1/lib/doc/new/room/guild/
dw_fluffos_v1/lib/doc/new/room/outside/
dw_fluffos_v1/lib/doc/new/room/storeroom/
dw_fluffos_v1/lib/doc/object/
dw_fluffos_v1/lib/doc/playtesters/
dw_fluffos_v1/lib/doc/policy/
dw_fluffos_v1/lib/doc/weapons/
dw_fluffos_v1/lib/global/handlers/
dw_fluffos_v1/lib/global/virtual/setup_compiler/
dw_fluffos_v1/lib/include/
dw_fluffos_v1/lib/include/cmds/
dw_fluffos_v1/lib/include/effects/
dw_fluffos_v1/lib/include/npc/
dw_fluffos_v1/lib/include/shops/
dw_fluffos_v1/lib/net/daemon/chars/
dw_fluffos_v1/lib/net/inherit/
dw_fluffos_v1/lib/net/intermud3/
dw_fluffos_v1/lib/net/intermud3/services/
dw_fluffos_v1/lib/net/obj/
dw_fluffos_v1/lib/net/save/
dw_fluffos_v1/lib/net/smnmp/
dw_fluffos_v1/lib/net/snmp/
dw_fluffos_v1/lib/obj/amulets/
dw_fluffos_v1/lib/obj/b_day/
dw_fluffos_v1/lib/obj/examples/
dw_fluffos_v1/lib/obj/food/alcohol/
dw_fluffos_v1/lib/obj/food/chocolates/
dw_fluffos_v1/lib/obj/food/fruits/
dw_fluffos_v1/lib/obj/food/meat/
dw_fluffos_v1/lib/obj/food/nuts/
dw_fluffos_v1/lib/obj/food/seafood/
dw_fluffos_v1/lib/obj/food/vegetables/
dw_fluffos_v1/lib/obj/fungi/
dw_fluffos_v1/lib/obj/furnitures/artwork/
dw_fluffos_v1/lib/obj/furnitures/bathroom/
dw_fluffos_v1/lib/obj/furnitures/beds/
dw_fluffos_v1/lib/obj/furnitures/cabinets/
dw_fluffos_v1/lib/obj/furnitures/chairs/
dw_fluffos_v1/lib/obj/furnitures/chests/
dw_fluffos_v1/lib/obj/furnitures/clocks/
dw_fluffos_v1/lib/obj/furnitures/crockery/
dw_fluffos_v1/lib/obj/furnitures/cupboards/
dw_fluffos_v1/lib/obj/furnitures/cushions/
dw_fluffos_v1/lib/obj/furnitures/fake_plants/
dw_fluffos_v1/lib/obj/furnitures/lamps/
dw_fluffos_v1/lib/obj/furnitures/mirrors/
dw_fluffos_v1/lib/obj/furnitures/outdoor/
dw_fluffos_v1/lib/obj/furnitures/safes/
dw_fluffos_v1/lib/obj/furnitures/shelves/
dw_fluffos_v1/lib/obj/furnitures/sideboards/
dw_fluffos_v1/lib/obj/furnitures/sofas/
dw_fluffos_v1/lib/obj/furnitures/stoves/
dw_fluffos_v1/lib/obj/furnitures/tables/
dw_fluffos_v1/lib/obj/furnitures/wardrobes/
dw_fluffos_v1/lib/obj/handlers/
dw_fluffos_v1/lib/obj/handlers/autodoc/
dw_fluffos_v1/lib/obj/jewellery/anklets/
dw_fluffos_v1/lib/obj/jewellery/bracelets/
dw_fluffos_v1/lib/obj/jewellery/earrings/
dw_fluffos_v1/lib/obj/jewellery/misc/
dw_fluffos_v1/lib/obj/jewellery/necklaces/
dw_fluffos_v1/lib/obj/jewellery/rings/
dw_fluffos_v1/lib/obj/media/
dw_fluffos_v1/lib/obj/misc/buckets/
dw_fluffos_v1/lib/obj/misc/jars/
dw_fluffos_v1/lib/obj/misc/papers/
dw_fluffos_v1/lib/obj/misc/player_shop/
dw_fluffos_v1/lib/obj/misc/shops/
dw_fluffos_v1/lib/obj/misc/traps/
dw_fluffos_v1/lib/obj/monster/
dw_fluffos_v1/lib/obj/monster/godmother/
dw_fluffos_v1/lib/obj/monster/transport/
dw_fluffos_v1/lib/obj/plants/inherit/
dw_fluffos_v1/lib/obj/potions/
dw_fluffos_v1/lib/open/boards/
dw_fluffos_v1/lib/save/autodoc/
dw_fluffos_v1/lib/save/bank_accounts/
dw_fluffos_v1/lib/save/boards/frog/
dw_fluffos_v1/lib/save/books/bed_catalog/
dw_fluffos_v1/lib/save/creators/
dw_fluffos_v1/lib/save/mail/
dw_fluffos_v1/lib/save/mail/p/
dw_fluffos_v1/lib/save/newsrc/b/
dw_fluffos_v1/lib/save/newsrc/c/
dw_fluffos_v1/lib/save/newsrc/d/
dw_fluffos_v1/lib/save/newsrc/f/
dw_fluffos_v1/lib/save/newsrc/p/
dw_fluffos_v1/lib/save/newsrc/s/
dw_fluffos_v1/lib/save/newsrc/w/
dw_fluffos_v1/lib/save/players/c/
dw_fluffos_v1/lib/save/players/d/
dw_fluffos_v1/lib/save/players/g/
dw_fluffos_v1/lib/save/players/p/
dw_fluffos_v1/lib/save/players/s/
dw_fluffos_v1/lib/save/soul/data/
dw_fluffos_v1/lib/save/tasks/
dw_fluffos_v1/lib/save/vaults/
dw_fluffos_v1/lib/secure/cmds/lord/
dw_fluffos_v1/lib/secure/config/
dw_fluffos_v1/lib/secure/items/
dw_fluffos_v1/lib/secure/player/
dw_fluffos_v1/lib/soul/
dw_fluffos_v1/lib/soul/i/
dw_fluffos_v1/lib/soul/j/
dw_fluffos_v1/lib/soul/k/
dw_fluffos_v1/lib/soul/o/
dw_fluffos_v1/lib/soul/q/
dw_fluffos_v1/lib/soul/to_approve/
dw_fluffos_v1/lib/soul/u/
dw_fluffos_v1/lib/soul/v/
dw_fluffos_v1/lib/soul/wish_list/
dw_fluffos_v1/lib/soul/y/
dw_fluffos_v1/lib/soul/z/
dw_fluffos_v1/lib/std/creator/
dw_fluffos_v1/lib/std/effects/
dw_fluffos_v1/lib/std/effects/attached/
dw_fluffos_v1/lib/std/effects/external/
dw_fluffos_v1/lib/std/effects/fighting/
dw_fluffos_v1/lib/std/effects/other/
dw_fluffos_v1/lib/std/environ/
dw_fluffos_v1/lib/std/guilds/
dw_fluffos_v1/lib/std/hospital/
dw_fluffos_v1/lib/std/house/
dw_fluffos_v1/lib/std/house/onebedhouse/
dw_fluffos_v1/lib/std/house/onebedhut/
dw_fluffos_v1/lib/std/house/tworoomflat/
dw_fluffos_v1/lib/std/languages/
dw_fluffos_v1/lib/std/liquids/
dw_fluffos_v1/lib/std/nationality/
dw_fluffos_v1/lib/std/nationality/accents/
dw_fluffos_v1/lib/std/nationality/accents/national/
dw_fluffos_v1/lib/std/nationality/accents/regional/
dw_fluffos_v1/lib/std/npc/goals/
dw_fluffos_v1/lib/std/npc/goals/basic/
dw_fluffos_v1/lib/std/npc/goals/misc/
dw_fluffos_v1/lib/std/npc/inherit/
dw_fluffos_v1/lib/std/npc/plans/
dw_fluffos_v1/lib/std/npc/plans/basic/
dw_fluffos_v1/lib/std/outsides/
dw_fluffos_v1/lib/std/races/shadows/
dw_fluffos_v1/lib/std/room/basic/topography/
dw_fluffos_v1/lib/std/room/controller/
dw_fluffos_v1/lib/std/room/controller/topography/
dw_fluffos_v1/lib/std/room/furniture/games/
dw_fluffos_v1/lib/std/room/furniture/inherit/
dw_fluffos_v1/lib/std/room/inherit/carriage/
dw_fluffos_v1/lib/std/room/inherit/topography/
dw_fluffos_v1/lib/std/room/punishments/
dw_fluffos_v1/lib/std/room/topography/area/
dw_fluffos_v1/lib/std/room/topography/iroom/
dw_fluffos_v1/lib/std/room/topography/milestone/
dw_fluffos_v1/lib/std/shadows/
dw_fluffos_v1/lib/std/shadows/attached/
dw_fluffos_v1/lib/std/shadows/curses/
dw_fluffos_v1/lib/std/shadows/disease/
dw_fluffos_v1/lib/std/shadows/fighting/
dw_fluffos_v1/lib/std/shadows/room/
dw_fluffos_v1/lib/std/shops/controllers/
dw_fluffos_v1/lib/std/shops/objs/
dw_fluffos_v1/lib/std/shops/player_shop/
dw_fluffos_v1/lib/std/shops/player_shop/office_code/
dw_fluffos_v1/lib/std/socket/
dw_fluffos_v1/lib/www/
dw_fluffos_v1/lib/www/external/autodoc/
dw_fluffos_v1/lib/www/external/java/telnet/Documentation/
dw_fluffos_v1/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v1/lib/www/external/java/telnet/examples/
dw_fluffos_v1/lib/www/external/java/telnet/tools/
dw_fluffos_v1/lib/www/pics/
dw_fluffos_v1/lib/www/secure/creator/
dw_fluffos_v1/lib/www/secure/editors/
dw_fluffos_v1/lib/www/secure/survey_results/
/*  -*- LPC -*-  */
/*
 * $Locker:  $
 * $Id: events.c,v 1.136 2003/10/29 18:25:27 pinkfish Exp $
 */
/**
 * This file contains all the standard event handling code that players
 * need.  This will handle things like informs, shouts, says, tells,
 * whispers.  Everything!   It formats the message correctly and
 * sends it to the player.
 * @author Pinkfish
 */
#include <dirs.h>
#include <living.h>
#include <player.h>
#include <telnet.h>
#include <term.h>
#include <tune.h>
#include <language.h>
#include <broadcaster.h>
#include <cmds/options.h>
#include <newbiehelpers.h>
#include <playerinfo.h>

#define DEBUG
// #define USE_ROLE_PLAYING_SHORTS
#define BROADCASTER "/obj/handlers/broadcaster"
#define SPACES "                                                              "

#define INFORM_COLOURS ([ "default":"WHITE", "logon":"GREEN", "death":"RED", \
                           "cheat":"RED", "multiplayer":"RED",  \
                           "bad-password" : "RED", "link-death":"GREEN", \
                           "new-player" : "BOLD%^%^MAGENTA", \
                           "gag" : "BOLD%^%^RED", "alert" : "GREEN" ])

#ifdef OLD_THINGY
inherit "/global/play_parse_com";
#else
inherit "/global/new_parse";
#endif
inherit "/global/communicate";
inherit "/global/friends";
inherit "/global/options_control";

/*
 * This contains the event related global variables.
 * We are very short on global variables and this reduces our need for them.
 */
class event_info {
  mapping colour_map;
  string cur_term;
  string last_term;
  object where;
  object *had_shorts;
  mixed *eemessages;
  mixed busy;
}

private nosave class event_info _event_info;

private int earmuffs;
private int cols;
private int rows;
private mapping my_colours;

/*
 * This so that changeing the definitions gets fixed
 * when they log in again.  Also keeps the save
 * file smaller.
 */
private string term_name = "network";
private string *inform_types;
private mixed *tell_history;

void set_my_colours(string event_type, string colour);
mapping query_my_colours();

string find_rel(string word, int from);
private int set_our_rows(int num);
private int set_our_cols(int num, int test);
private int do_busy(string str);
private int do_busy_player(object *players);
protected varargs int do_tell_his(string, int);
mixed query_property(string name);
string query_nationality_accent_ob();

void create() {
  friends::create();
  _event_info = new(class event_info,
                    eemessages : ({ }));
                    
  my_colours = ([ ]);
  inform_types = ({ });
#ifdef OLD_THINGY
  play_parse_com::create();
#else
  new_parse::create();
#endif
} /* create() */

#if !efun_defined(has_mxp)
private int has_mxp(object ob) {
   return 0;
}
#endif

/**
 * This method returns the current terminal name.  If this is set to
 * network then the network will be queried for the terminal type
 * (using telnet suboption negotiation).
 * @return the current terminal name
 * @see query_cur_term()
 * @see set_term_type()
 */
string query_term_name() { return term_name; }
/**
 * This method returns the current terminal type that is being used.  This
 * will be 0 if the terminal name is set to network and no response has
 * been gained from the remote site yet.  Otherwise it should be the
 * same value as the terminal name.
 * @return the current terminal type
 * @see query_term_name()
 * @see set_term_type()
 */
string query_cur_term() { return _event_info->cur_term; }
/**
 * This method tells us if the player currently has earmuffs turned on.
 * @return 1 if earmuffs are on, 0 if they are not
 * @see check_earmuffs()
 * @see toggle_earmuffs()
 */
int query_earmuffs() { return earmuffs; }

/**
 * This method returns the list of inform types this player can receive.
 * @return array of inform types
 */
string *query_inform_types() {
  string *types;
  
  types = ({ "logon", "new-player", "birthday", "council", "friend" });
    
  if (this_object()->query_creator()) {
    types += ({ "link-death", "message", "death",
               "guild", "delete", "help", "combat-debug", "skill", "quest",
               "multiplayer", "bad-password", "club", "debug", "gag", 
               "alert" });

    if (master()->query_lord((string)this_object()->query_name())) {
      types += ({ "force", "enter", "dest", "cheat", "xp", "calls",
                    "cpu", "ftp" });
    }
  } else if ( load_object(NEWBIEHELPERS_HANDLER)->query_helper_access(this_object())
                ) {
      types += ({ "guild" });
  }

  if( this_object()->query_guild_ob() == "/std/guilds/witch" ||
      this_object()->query_creator() ) {
    types += ({ "mockery" });
  }

  return types;
}

/* This is pulled back into this object for security reasons... */
/**
 * This is the command to handle the inform stuff.
 * It does all the turning on/off and stuff things for the informs.
 * @param str the informs to listen to
 * @see event_inform()
 */
nomask protected int do_inform(string str) {
  string type, *types, *on, *frog, *off, *failed;
  int i;

  types = query_inform_types();
  foreach(type in inform_types) {
    if(member_array(type, types) == -1) {
      inform_types -= ({ type });
    }
  }

  on = inform_types;
  
  if (!on) {
    on = ({ });
  }
  if (!str) {
    str = "";
  }
  frog = explode(str, " ");
  if (!frog) {
    frog = ({ });
  } else {
    frog -= ({ "", 0 });
  }
  if (!sizeof(frog)) {
    /* show status */
    if (this_object()->query_property("inform repressed")) {
      write("Your informs are currently being repressed.\n");
    }
    if (sizeof(on)) {
      write("$I$5=You will be informed of "+ query_multiple_short(on)+
            " events.\n");
    }
    types -= on;
    if (sizeof(types)) {
      write("$I$5=You are not being informed of "+ query_multiple_short(types)+
            " events.\n");
    }
    return 1;
  }
  if (sizeof(frog) == 1) {
    switch (frog[0]) {
    case "on" :
      this_object()->remove_property("inform repressed");
      write("You are now being informed.  This is true!\n");
      if (sizeof(on)) {
         write("$I$5=You will be informed of "+ query_multiple_short(on)+
               " events.\n");
      } else {
         write("$I$5=Although you are not currently being informed of "
               "any events.\n");
      }
      return 1;
    case "off":
      this_object()->add_property("inform repressed", 1);
      write("Informs are now repressed.\n");
      return 1;
    case "all":
      on = types;
      frog = frog[1..];
      break;
    case "none" :
      on = ({ });
      write("You will not be informed of anything.\n");
      frog = frog[1..];
      break;
    }
  }
  failed = off = ({ });
  for (i=0;i<sizeof(frog);i++) {
    if (member_array(frog[i], types) == -1) {
      failed += ({ frog[i] });
    } else {
      if (sizeof(frog) > i+1) {
        switch (frog[i+1]) {
        case "on" :
          if (member_array(frog[i], on) == -1)
            on += ({ frog[i] });
          i++;
          break;
        case "off" :
          off += ({ frog[i] });
          i++;
          break;
        default :
          if (member_array(frog[i], on) == -1) {
            on += ({ frog[i] });
          } else {
            off += ({ frog[i] });
          }
          break;
        }
      } else {
        if (member_array(frog[i], on) == -1) {
          on += ({ frog[i] });
        } else {
          off += ({ frog[i] });
        }
      }
    }
  }
  on -= off;
  if (sizeof(failed)) {
    write("$I$5=I don't know about "+ query_multiple_short(failed)+
          " events.\n");
  }
  if (sizeof(off)) {
    write("$I$5=You will now not be informed of "+ query_multiple_short(off)+
          " events.\n");
  }
  if (sizeof(on)) {
    write("$I$5=You will now be informed of "+ query_multiple_short(on)+
          " events.\n");
  }
  inform_types = on;
  return 1;
} /* do_inform() */

/**
 * This method tests to see if the player can see octarine objects.
 * @return 1 if they can see octarine, 0 if they cannot
 */
int query_see_octarine() {
  string guild;

  if ( this_object()->query_creator() )
    return 1;
  if(!(guild = (string)this_object()->query_guild_ob())) return 0;
  return (int)guild->query_see_octarine();
} /* query_see_octarine() */

/**
 * This method will do the octarine checking for you on the message.
 * @param str the string to check
 * @see query_see_octarine()
 * @example
 * string query_long_bit() {
 *   return "Glinting and sharp looking, the long sword is an impressive "
 *          "weapon in the hands of someone knowledgeable.\n" +
 *          this_player()->octarine_message("It glows with a fluffy octarine "
 *                                          "aura.\n");
 * } /\* query_long_bit() *\/
 */
string octarine_message(string str) {
  if (query_see_octarine())
    return str;
  return "";
} /* octarine_message() */

/**
 * This function returns the appropriate colour codes for the given event
 * type. It will return the players chosen colour if they've set one or
 * the default if not.
 *
 * @param event_type The type of event
 * @return a string of colour codes.
 */
string colour_event(string event_type, string default_colour) {
  if (my_colours[event_type]) {
    return replace(my_colours[event_type], " ", "");
  }

  if (!default_colour) {
    return "";
  }

  return default_colour;
} /* colour_event() */

/**
 * This method handles the conversersions for the colour mapping which is
 * done on Discworld.  This also does octarine message expansion, if the
 * keyword %\^OCTARINE:message%\^ is embeded into a string then the
 * inside section will be replaced with a blank string if the player
 * cannot see octarine messages.
 * @param str the string to do the conversion on
 * @param width the width of the string
 * @param indent the size of the indent
 * @param args any other arguments
 * @return the fixed up string
 * @see efun::terminal_colour()
 */
varargs string fix_string(string str, int width, int indent, int padding, mixed *args ...) {
  string octmess, *bits, bit;
  int i;

  if (!stringp(str) || str == "") {
    return str;
  }

  if(indent > width / 3) {
    indent = 4;
  }

  if (!_event_info->cur_term) {
    if (term_name != "network") {
      _event_info->cur_term = term_name;
    } else {
      _event_info->cur_term = "dumb";
    }
  }
  if (!_event_info->colour_map) {
    _event_info->colour_map = (mapping)TERM_HANDLER->set_term_type(_event_info->cur_term, query_property(PLAYER_ALLOW_COLOURED_SOULS));
  }
  if (sizeof(args)) {
    str = sprintf(str, args ...);
  }
  bits = explode(str, "%^OCTARINE:");
  foreach (bit in bits) {
    i = strsrch(bit, "%^");
    if (i == -1) {
      continue;
    }
    octmess = bit[0..i-1];
    if (query_see_octarine()) {
      str = replace_string(str, sprintf("%%^OCTARINE:%s%%^", octmess),
                           octmess);
    } else {
      str = replace_string(str, sprintf("%%^OCTARINE:%s%%^", octmess), "");
    }
  }
  // If someone has mxp then we can do the formatting in a different
  // way.
  if (is_mxp_enabled()) {
  //if (query_name() == "greenland") {
    str = terminal_colour(str, _event_info->colour_map);
  } else {
    str = terminal_colour(str, _event_info->colour_map, width, indent);
  }
  return str;
} /* fix_string() */

/* Send all the relevant junk down to get the information we want. */
/** @ignore yes */
void player_connected() {
  _event_info->last_term = 0;
  /* Turn on the option */
  printf("%c%c%c", IAC, DO, TELOPT_TTYPE);
  /* Get them to send us their first terminal type */
  printf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE);
  /* Get them to send us their window size */
  printf("%c%c%c", IAC, DO, TELOPT_NAWS);
} /* player_connected() */

/**
 * This method sets the current terminal type for the player.  If the type
 * is network, then the network will be queried for the terminal type
 * and that will be used.  This is the distiction between the current
 * terminal type and the terminal name.  The name will be the value that
 * is set by the player and the current type will be the information
 * garnered from the network (if the name is network) or the same as the
 * name.
 * @param str the new terminal type
 * @return 1 if the terminal was successful set, 0 if not
 * @see set_term()
 * @see query_term_name()
 * @see query_cur_term()
 */ 
int set_term_type(string str) {
  if (!str) {
    notify_fail(sprintf("%-=*s", cols,
                "Syntax: "+query_verb()+" <term_type>\n"+
                "Where term type is one of the following: "+
                implode((string *)TERM_HANDLER->query_term_types(), ", ")+
                ".\nOr set it to \"network\", and the mud will try to "
                "figure it out itself.\n"));
    return 0;
  }
  if(str != term_name) {
    if (member_array(str, (string *)TERM_HANDLER->query_term_types()) != -1 ||
        str == "network") {
      if (str != "network") {
        _event_info->colour_map = (mapping)TERM_HANDLER->set_term_type(str, query_property(PLAYER_ALLOW_COLOURED_SOULS));
      } else { /* Get em to send us our terminal type */
        player_connected();
      }
      term_name = str;
      _event_info->cur_term = 0;
      write("Ok, terminal type set to "+str+".\n");
      return 1;
    } else {
      notify_fail("No such terminal type as " + str  + ".\n");
      return 0;
    }
  } else {
    notify_fail("Terminal type unchanged as " + str + ".\n");
    return 0;
  }
} /* set_term_type() */

/** @ignore yes */
void set_term(string name) {
  term_name = name;
  _event_info->cur_term = 0;
} /* set_term() */

/**
 * This method handles the responses from the remote site informing
 * us of their terminal type.
 * @param name the terminal type gathered from the remote site
 * @return 0 if the type was not used, 1 if it was
 * @see set_term_type()
 * @see query_term_name()
 * @see query_cur_term()
 */
int set_network_terminal_type(string name) {
  if (term_name != "network") return 0;
  if (!name) {
    _event_info->cur_term = "dumb";
    _event_info->colour_map = 0;
  }
  if (_event_info->colour_map =
      (mapping)TERM_HANDLER->set_network_term_type(name, query_property(PLAYER_ALLOW_COLOURED_SOULS))) {
    _event_info->cur_term = name;
    return 1;
  }
} /* set_network_terminal_type() */

/**
 * This method resets the colour map information on the player.  THis is
 * called when some change is made to the terminal data and it needs to
 * be updated.
 */
void reset_colour_map() {
   _event_info->colour_map = 0;
}

/*
mapping query_debug_colour_map() {
   return _event_info->colour_map;
}
 */

/** 
 * This method adds all the event commands onto the player.
 * This will be called in the player startup sequence.
 */
void event_commands(){
  add_command("rows", this_object(), "", (: set_our_rows(0) :));
  add_command("cols", this_object(), "", (: set_our_cols(0, 0) :));
  add_command("rows", this_object(), "<number>", (: set_our_rows($4[0]) :));
  add_command("cols", this_object(), "<number>", (: set_our_cols($4[0], 0) :));
  add_command("cols", this_object(), "test <number>", (: set_our_cols($4[0], 1) :));
  add_command("term", this_object(), "{" + 
                implode((string *)TERM_HANDLER->query_term_types() +
                ({ "network" }), "|")+"}", (: set_term_type($4[0]) :));
  add_command("term", this_object(), "", (: set_term_type(0) :));
  add_command("inform", this_object(), "", (: do_inform(0) :));
  add_command("inform", this_object(), "<string>", (: do_inform($4[0]) :));
  
  /* If a liaison or a lord... */
  if (this_object()->query_creator()) {
    add_command("busy", this_object(), "{on|off}", (: do_busy($4[0]) :));
    add_command("busy", this_object(), "<indirect:player>",
                (: do_busy_player($1) :));

  }
}

/**
 * Return function pointer for do_tell_his, for htell only.
 */

function get_htell_func(){
  if(file_name(previous_object()) != "/cmds/player/ht_ell")
    return 0;
  return (:do_tell_his:);
}

/**
 * This method is the command used to print a players tell history.
 */
protected varargs int do_tell_his(string str, int brief) {
  string ret;
  mixed bit, *filter_history;

  if (str != "")  {
    filter_history = filter(tell_history,
                            (: strsrch(lower_case($1[0]), $(str)) > -1 :));
  }
  else filter_history = tell_history;
  if (!pointerp(filter_history) || !sizeof(filter_history)) {
    return notify_fail("You have not been told anything.\n");
  }
  if (undefinedp(brief))  brief = 0;
  ret = "$P$Tell History$P$Your tell history is:\n";
  foreach (bit in filter_history) {
    if (!brief) {
      ret += "** "+ctime(bit[2])+" **\n";
    }
    ret += fix_string("%s%s\n", cols, strlen(bit[0]), 0, bit[0], bit[1]);
  }
  write(ret);
  return 1;
} /* do_tell_his() */

/**
 * This method handles setting the busy flag.  The busy flag can only
 * be set by liaisons and lords, why lords?  Just because :)  This
 * command was inspired by moonchild.
 * @param str the on or off string
 * @return 1 on success, 0 on failure
 */
int do_busy(string str) {
   if (str == "on") {
      _event_info->busy = 1;
   } else {
      _event_info->busy = 0;
   }
   write("Busy set to " + str + ".\n");
   return 1;
} /* do_busy() */

/**
 * This method allows creators to set the player for whom they are currently
 * busy too.
 * @param obs the player to be busy with
 * @return 1 on success, 0 on failure
 */
int do_busy_player(object *obs) {
   write("Ok, setting you as busy with " + query_multiple_short(obs) + ".\n");
   _event_info->busy = obs;
   return 1;
} /* do_busy_player() */

/**
 * This method tells us if the player/creator/lord is currently in busy
 * mode.  This will be 1 if the creatopr is generaly busy, or
 * it will return the array of players they are busy with.
 * @return the busy mode flag
 */
mixed query_busy() {
   if (pointerp(_event_info->busy)) {
      _event_info->busy -= ({ 0 });
   }
   if (pointerp(_event_info->busy) && !sizeof(_event_info->busy)) {
      _event_info->busy = 0;
   }
   return _event_info->busy;
} /* query_busy() */
 
/**
 * This method will change the current value of the earmuffs on the player.
 * @see check_earmuffs()
 * @see query_earmuffs()
 */
void toggle_earmuffs() {
  earmuffs = !earmuffs;
} /* toggle_earmuffs() */

/**
 * This method will set the system to allow friends to punch through
 * earmuffs.
 * @see check_earmuffs()
 * @see query_earmuffs()
 */
void set_allow_friends_earmuffs() {
  earmuffs = PLAYER_ALLOW_FRIENDS_EARMUFF;
} /* toggle_earmuffs() */

/**
 * This method checks to see if a particular event is earmuffed.
 * @param type the type of event to check
 * @param person the person who is being checked for the earmuffing of
 * @return 1 if the event is earmuffed and 0 if it is not
 * @see toggle_earmuffs()
 * @see query_earmuffs()
 * @example
 * obs = users();
 * 
 * obs = filter(obs, (: $1->check_earmuffs("shout", this_player()) :) );
 * // Do the shout
 */
int check_earmuffs(string type, object person) {
  string *on;

  if (!earmuffs) {
    return 0;
  }
  on = (string *)this_object()->query_property(PLAYER_EARMUFF_PROP);
  if (!on) {
     return 0;
  }
  if (member_array(type, on) == -1) {
    return 0;
  }
  // If they are a friend they punch through
  if (!person) {
    person = this_player();
  }
  if (person && earmuffs == PLAYER_ALLOW_FRIENDS_EARMUFF) {
    if (is_friend(person->query_name())) {
      return 0;
    }
  }
  return 1;
} /* check_earmuffs() */

/**
 * This method sets the number of rows on the players screen.
 * @param i the new number of rows
 * @see query_rows()
 */
void set_rows(int i) {
  if (i < 5) {
     return ;
  }
  rows = i;
} /* set_rows() */

/**
 * This method returns the current number of rows the player has
 * set on their screen.
 * @return the number of rows on the screen
 * @see set_rows()
 */
int query_rows() { return rows; }

private int set_our_rows(int val) {
  if (!val) {
    notify_fail("Rows currently set to " + rows + ".\nrows <number> to set.\n");
    return 0;
  }
  if (val <= 10) {
    notify_fail("Invalid number of rows.\n");
    return 0;
  }
  write("Rows set to " + val + ".\n");
  rows = val;
  return 1;
} /* set_our_rows() */

/**
 * This method returns the current number of columns the player has
 * set on their screen.
 * @return the number of columns on the screen
 * @see set_cols()
 */
int query_cols() { return cols; }

/**
 * This method sets the current number of columns the player has set on
 * their screen.
 * @param i the new number of columns
 * @see query_cols()
 */
void set_cols(int i) {
  if (i <= 10 || i > 999)
     return ;
   cols = i;
} /* set_cols() */

private int set_our_cols(int val, int test) {
  int cur;

  if(!val) {
    notify_fail("Columns currently set to " + cols + ".\ncols <number> to set.\n");
    return 0;
  }
  if(val <= 35 || val > 999) {
    notify_fail("Invalid column size.\n");
    return 0;
  }

  if (test)  {
    cur = cols;
    cols = val;
    /* Watch this.... */
    write(implode(allocate(val, (: sprintf("%d", ($1 + 1) % 10) :)), "") + "\n");
    call_out((: cols = $(cur) :), 3);
    return 1;    
  }
  write("Columns set to " + val + ".\n");
  cols = val;
  return 1;
} /* set_our_cols() */

/**
 * set the colour codes for a given event
 */
void set_my_colours(string event_type, string colour) {
  if(colour == "default") {
    map_delete(my_colours, event_type);
  } else if(colour == "none") {
    my_colours[event_type] = "";
  } else {
    my_colours[event_type] = colour;
  }
}

/**
 * Return a players list of custom colours.
 * @return a mapping of the players custom colours for different events.
 */
mapping query_my_colours() {
  return my_colours;
}

void set_looked( object thing ) { _event_info->where = thing; }

/**
 * This method does all those terrible things with messages and $'s
 * turning them into real strings.  It is a neat function if somewhat
 * complicated :)  It was written by Deutha.
 * <p>
 * The return array has two elements, the first being the reformed
 * message and the second being the reformed things array.
 * @param message the message to reform
 * @param things some bonus things to reform it with
 * @return an array consisting of two elements
 */
mixed *reform_message( string message, mixed *things ) {
   int last, number;
   string before, middle, after, info;

   last = -1;
   if ( !things ) {
      things = ({ });
   } else {
      last = sizeof(things) - 1;
   }
   if ( !_event_info->where ) {
      _event_info->where = environment();
   }
   if (strsrch(message, "$L$") != -1) {
      while ( sscanf( message, "%s$L$%s$L$%s", before, middle, after ) == 3 ) {
         if (sscanf( middle, "[%s]%s", info, middle) == 2) {
            if (info[0..4] == "read:") {
               middle = LANGUAGE_HAND->garble_text(info[5..], middle, 0, this_object());
            } else {
               middle = LANGUAGE_HAND->garble_text_say(middle, info, this_object());
            }
         }
         message = sprintf("%s%s%s", before, middle, after);
      }
   }

   if (strsrch(message, "$R$") != -1) {
      while ( sscanf( message, "%s$R$%s$R$%s", before, middle, after ) == 3 ) {
         if ( sscanf( middle, "[%s]%s", info, middle ) != 2 ) {
            info = "";
         }
         switch ( middle[ 0 ] ) {
            case '-' :
               number = 0;
               middle = middle[ 1 .. ];
               break;
            case '+' :
               number = 1;
               middle = middle[ 1 .. ];
               break;
            default :
               number = 2;
         }
         if ( ( number == 2 ) || _event_info->where->query_relative( middle ) ) {
            if ( this_object()->query_creator() ) {
               message = sprintf("%s%s (%s)%s", before, find_rel(middle, number),
                                 middle, after);
            } else {
               message = sprintf("%s%s%s", before, find_rel(middle, number),
                                 after);
            }
         } else {
            message = sprintf("%s%s%s%s", before, info, middle, after);
         }
      }
   }
   if (strsrch(message, "$r$") != -1) {
      while ( sscanf( message, "%s$r$%s$r$%s", before, middle, after ) == 3 ) {
         if ( sscanf( middle, "[%s]%s", info, middle ) != 2 ) {
            info = "";
         }
         switch ( middle[ 0 ] ) {
            case '-' :
               number = 0;
               middle = middle[ 1 .. ];
               break;
            case '+' :
               number = 1;
               middle = middle[ 1 .. ];
               break;
            default :
               number = 2;
         }
         if ( ( number == 2 ) || _event_info->where->query_relative( LENGTHEN[ middle ] ) ) {
            if ( this_object()->query_creator() ) {
               message = sprintf("%s%s (%s)%s", before,
                                 SHORTEN[find_rel(LENGTHEN[middle], number)],
                                 middle, after);
            } else {
               message = sprintf("%s%s%s", before,
                                 SHORTEN[find_rel(LENGTHEN[middle], number)],
                                 after);
            }
         } else {
            message = sprintf("%s%s%s%s", before, info, middle, after);
         }
      }
   }
#ifdef DEBUG
   if ( this_object()->query_property( "see eemessages" ) )
      efun::tell_object( this_object(), "Looking at "+ message +".\n" );
#endif   
   if (strsrch(message, "$M$") != -1) {
      while ( sscanf( message, "%s$M$%s$M$%s", before, middle, after ) == 3 ) {
#ifdef DEBUG     
         if ( this_object()->query_property( "see eemessages" ) )
            efun::tell_object( this_object(), "Expanding "+ middle +".\n" );
#endif      
         last++;
         message = sprintf("%s$%d$%s", before, last, after);
         things += ({ ({ }) });
         if (strsrch(middle, "$") == -1) {
            things[ last ] += ({ middle });
            middle = 0;
         } else {
            while ( sscanf( middle, "$%s$%s", info, middle ) == 2 ) {
#ifdef DEBUG        
               if ( this_object()->query_property( "see eemessages" ) ) {
                  efun::tell_object( this_object(), "Found "+ info +".\n" );
               }
#endif      
               things[ last ] += ({ "my_"+ info });
            }
         }
      }
   }
   if (strsrch(message, "$") != -1) {
      after = message;
      message = "";
      while ( sscanf( after, "%s$%s$%s", before, middle, after ) == 3 ) {
#ifdef DEBUG     
         if ( this_object()->query_property( "see eemessages" ) )
            efun::tell_object( this_object(), "Trying "+ middle +".\n" );
#endif      
         if ( sscanf( middle, "%s_short:%s", middle, info ) != 2 ) {
            message = sprintf("%s%s$%s", message, before, middle);
            after = sprintf("$%s", after);
            continue;
         }
         last++;
         message = sprintf("%s%s$%d$", message, before, last);
         things += ({ ({ sprintf("my_%s_short:%s", middle, info) }) });
      }
      message += after;
   }
   return ({ message, things });
} /* reform_message() */

/**
 * This adds a message into the current list of printable messages.  This
 * will be squided up together and printed out slightly later, this handles
 * the concatenating of enter messages, and soul messages.  Etc.
 * @param message the message to add
 * @param things the objects which are involved with the message
 * @see reform_message()
 */
void add_message( string message, mixed *things ) {
   int last;
   mixed *stuff;

   if ( !interactive( this_object() ) ) {
      return;
   }
   if ( strsrch( message, "$" ) == -1 ) {
      stuff = ({ message, things });
   } else  {
      stuff = reform_message( message, things );
   }
   _event_info->where = 0;
   if ( !sizeof( _event_info->eemessages ) ) {
      _event_info->eemessages = stuff;
   } else {
      last = sizeof( _event_info->eemessages ) - 2;
      if ( ( stuff[ 0 ] == _event_info->eemessages[ last ] ) &&
            ( sizeof( stuff[ 1 ] ) == 1 ) ) {
         if ( sizeof( filter( stuff[ 1 ][ 0 ], (: member_array($1, $2) != -1 :),
               _event_info->eemessages[ last + 1 ][ 0 ] ) ) ) {
            _event_info->eemessages += stuff;
         } else {
            _event_info->eemessages[ last + 1 ][ 0 ] += stuff[ 1 ][ 0 ]; 
         }
      } else {
         _event_info->eemessages += stuff;
      }
   }
#ifdef DEBUG
   if ( this_object()->query_property( "see eemessages" ) )
      efun::tell_object( this_object(), sprintf( "%O\n", _event_info->eemessages ) );
#endif   
} /* add_message() */

/**
 * @ignore yes 
 * This method is used for the reform_mesage stuff
 */
string get_pretty_short( object thing, int dark ) {
  if (dark && environment(thing) != this_object()) {
    if (living(thing) && thing->query_race_ob() &&
        (thing->query_race_ob())->query_humanoid()) {
      return "someone";
    } else {
      return "something";
    }
  }

  if ( !thing->query_visible( this_object() ) ) {
    if (living(thing) && thing->query_race_ob() &&
        (thing->query_race_ob())->query_humanoid()) {
      return "someone";
    } else {
      return "something";
    }
  }

#ifdef USE_ROLE_PLAYING_SHORTS
   if(interactive(thing) &&
      this_object()->query_role_playing() &&
      !this_object()->is_friend(thing->query_name())) {
     return thing->query_short_desc();
   }
#endif
   
   return (string)thing->pretty_short( this_object() ) +
         (string)thing->hide_invis_string();
} /* get_pretty_short() */

/**
 * @ignore yes
 * This method is used for the reform_mesage stuff
 */
string get_pretty_plural( object thing, int dark ) {
   if (dark && environment(thing) != this_object()) {
      if (living(thing)) {
         return "people";
      } else {
         return "things";
      }
   }

   if ( !thing->query_visible( this_object() ) ) {
      return "things";
   }

#ifdef USE_ROLE_PLAYING_SHORTS
   if(interactive(thing) &&
      this_object()->query_role_playing() &&
      !this_object()->is_friend(thing->query_name())) {
     return thing->query_plural_desc();
   }
#endif

   return (string)thing->pretty_plural( this_object() ) +
         (string)thing->hide_invis_string();
} /* get_pretty_plural() */

/**
 * This is a special function for use with the reform message, it allows
 * the string to be echoed into the list instead of using the object's
 * value itself.  This is done specifically to handle objects with
 * variable shorts, so we get the short description correct at the
 * moment it is queried.
 */
string my_mirror_short( object thing, string arg) {
   if (objectp(thing)  &&  userp(thing))
      return thing->short(0, 0);
   return arg;
} /* my_mirror_short() */

/**
 * @ignore yes
 * This method is used for the reform_mesage stuff
 */
string my_a_short( object thing, string arg, int dark) {
   string article;

   if (!thing) {
      return "something";
   }
   if (dark && environment(thing) != this_object()) {
      // Allow remote shorts to work.
     if (living(thing) && thing->query_race_ob() &&
         (thing->query_race_ob())->query_humanoid()) {
       if (environment(thing) != environment()) {
         return "someone";
       }
     } else {
       return "something";
     }
   }

   if ( !objectp( thing ) ) {
     return "an unknown object";
   }

   article = (string)thing->query_determinate( this_object() );
   if ( !article ) {
      return add_a( (string)this_object()->get_pretty_short( thing, dark ) );
   }
   return article + (string)this_object()->get_pretty_short( thing, dark );
} /* my_a_short() */

/**
 * @ignore yes
 * This method is used for the reform_mesage stuff
 */
string my_the_short( object thing, string arg, int dark ) {
   string article;

   if (dark && environment(thing) != this_object()) {
      // Allow remote shorts to work.
     if (living(thing) && thing->query_race_ob() &&
         (thing->query_race_ob())->query_humanoid()) {
         if (environment(thing) == environment()) {
            return "someone";
         }
      } else {
         return "something";
      }
   }

   if ( !objectp( thing ) ) {
      return "the unknown object";
   }

   article = (string)thing->query_determinate( this_object() );
   if ( !article || ( article == "a " ) || ( article == "an " ) )
      return "the "+ (string)this_object()->get_pretty_short( thing, dark );
   return article + (string)this_object()->get_pretty_short( thing, dark );
} /* my_the_short() */

int some_more( string word ) {
    return sizeof( filter( all_inventory( _event_info->where ),
        (: $1->query_plural() == $(word) &&
           $1->query_visible(this_object()) :))) > 1;
} /* some_more() */

/**
 * @ignore yes
 * This method is used for the reform_mesage stuff
 */
string my_one_short( object thing, string arg, int dark ) {
   string article, its_plural;

   if (dark && environment(thing) != this_object()) {
      // Allow remote shorts to work.
     if (living(thing) && thing->query_race_ob() &&
         (thing->query_race_ob())->query_humanoid()) {
         if (environment(thing) == environment()) {
            return "someone";
         }
      } else {
         return "something";
      }
   }

   if ( !objectp( thing ) ) {
      return "one of the unknown objects";
   }
   if ( environment( thing ) != environment() ) {
      _event_info->where = this_object();
   } else {
      _event_info->where = environment();
   }

   /* return my_a_short( thing ); */
   article = (string)thing->query_determinate( this_object() );
   if ( !article || ( article == "a " ) || ( article == "an " ) ) {
      its_plural = (string)this_object()->get_pretty_plural( thing, dark );
      if ( some_more( its_plural ) ) {
         return "one of the "+ its_plural;
      }
      return "the "+ (string)this_object()->get_pretty_short( thing, dark );
   }
   return article + (string)this_object()->get_pretty_short( thing, dark );
} /* my_one_short() */

/**
 * @ignore yes
 * This method is used for the reform_mesage stuff
 */
string my_poss_short(object thing, string arg, int dark) {
   string its_plural;
   string article;
   string of_whom;

   if (dark && environment(thing) != this_object()) {
      // Allow remote shorts to work.
     if (living(thing) && thing->query_race_ob() &&
         (thing->query_race_ob())->query_humanoid()) {
         if (environment(thing) == environment()) {
            return "someone";
         }
      } else {
         return "something";
      }
   }

   if ( !objectp( thing ) ) {
      return "an unknown object";
   }
   if(living(thing)) {
     if (thing == this_object()) {
       return "your";
     } else {
       of_whom = this_object()->get_pretty_short( thing, dark );
       if(of_whom[<1] == 's')
         of_whom = of_whom + "'";
       else
         of_whom = of_whom +"'s";
       return of_whom;
     }
   }
   _event_info->where = environment( thing );
   if ( !_event_info->where ) {
      return my_a_short( thing, arg, dark );
   }
   if ( !living( _event_info->where ) && !_event_info->where->query_corpse() ) {
      return my_a_short( thing, arg, dark );
   }
#ifdef DEBUG
   if ( this_object()->query_property( "see eemessages" ) )
      efun::tell_object( this_object(), sprintf( "%O\n", _event_info->had_shorts ) );
#endif   
   if ( _event_info->where == this_object() ) {
      of_whom = "your ";
   } else {
      if ( member_array( _event_info->where, _event_info->had_shorts ) != -1 ) {
         of_whom = (string)_event_info->where->query_possessive() +" ";
      } else {
        of_whom = my_the_short( _event_info->where, arg, dark );
        if(of_whom[<1] == 's') {
          of_whom = of_whom + "' ";
        } else {
          of_whom = of_whom +"'s ";
        }
      }
   }
   if ( !article || ( article == "a " ) || ( article == "an " ) ) {
      its_plural = (string)this_object()->get_pretty_plural( thing, dark );
      if ( some_more( its_plural ) ) {
         return "one of "+ of_whom + its_plural;
      }
   }
   return of_whom + (string)this_object()->get_pretty_short( thing, dark );
}

/**
 * @ignore yes
 * This method is used for the reform_mesage stuff
 */
string my_the_poss_short(object thing, string arg, int dark) {
   string its_plural;
   string article;
   string of_whom;

   if (dark && environment(thing) != this_object()) {
      // Allow remote shorts to work.
      if (living(thing)) {
         if (environment(thing) == environment()) {
            return "someone's";
         }
      } else {
         return "something's";
      }
   }

   if ( !objectp( thing ) ) {
      return "an unknown object's";
   }

   article = (string)thing->query_determinate(this_object());
   if(!article || (article == "a " || article == "an "))
     article = "the ";

   if(living(thing)) {
     if (thing == this_object()) {
       return "your";
     } else {
       of_whom = this_object()->get_pretty_short( thing, dark );
       if(of_whom[<1] == 's')
         of_whom = of_whom + "'";
       else
         of_whom = of_whom +"'s";
       return article + of_whom;
     }
   }
   _event_info->where = environment( thing );
   if ( !_event_info->where ) {
      return my_the_short( thing, arg, dark );
   }
   if ( !living( _event_info->where ) && !_event_info->where->query_corpse()) {
      return my_the_short(thing, arg, dark);
   }
#ifdef DEBUG
   if ( this_object()->query_property( "see eemessages" ) )
      efun::tell_object(this_object(), sprintf("%O\n",
                                               _event_info->had_shorts));
#endif   
   if ( _event_info->where == this_object() ) {
     of_whom = "your ";
   } else {
     if(member_array( _event_info->where, _event_info->had_shorts ) != -1) {
       debug_printf("Had shorts");
       of_whom = (string)_event_info->where->query_possessive() +" ";
     } else {
       of_whom = my_the_short(_event_info->where, arg, dark);
       if(of_whom[<1] == 's') {
         of_whom = of_whom + "' ";
       } else {
         of_whom = of_whom +"'s ";
       }
     }
   }
   
   its_plural = (string)this_object()->get_pretty_plural( thing, dark );
   if(some_more(its_plural))
     return "one of "+ article + of_whom + its_plural;
   
   return of_whom + article + this_object()->get_pretty_short(thing, dark);
}

/** @ignore yes */
protected void clear_event_info_had_shorts() { _event_info->had_shorts = ({ }); }

/**
 * @ignore yes
 * This method is used for the reform_mesage stuff
 */
varargs string calc_shorts( string *short_list, int exact ) {
   int i;
   int dark;
   string list;
   string str;
   string desc;
   object ob;
   object *things;
   //mapping shorts;
   // These next two are tied.
   string *descs_str;
   mixed *descs_ob;
   mixed *parts;
   function number;

   descs_str = ({ });
   descs_ob  = ({ });
   if (!_event_info->had_shorts)  clear_event_info_had_shorts();
   if (exact) {
      number = (: query_num($1) :);
   } else {
      number = (: query_num($1, 20) :);
   }
   if (environment()) {
      dark = this_object()->check_dark(environment()->query_light());
   }
   foreach (str in short_list) {
      parts = explode( str, ":" );
      if (sizeof(parts) == 2) {
         ob = find_object( parts[ 1 ] );
      } else if (sizeof(parts) > 2) {
         parts[1] = implode(parts[ 1.. ], ":");
         ob = find_object( parts[1] );
      } else {
         ob = 0;
         parts += ({ "" });
      }
#ifdef DEBUG
      if ( this_object()->query_property( "see eemessages" ) )
         efun::tell_object( this_object(), sprintf( "%O\n", ob ) );
#endif      
      if (ob) {
         _event_info->had_shorts = ({ ob }) + _event_info->had_shorts;
      }
      if ( ob == this_object() ) {
         if (parts[0] == "my_poss_short" || parts[0] == "my_the_poss_short") {
            desc = "your";
         } else {
            desc = "you";
         }
      } else if (sizeof(parts) >= 2) {
#ifdef DISBALED
        // We were crashing a lot in this call so the code below is a
        // workaround attempt to see if we can prevent the crashing.
         desc = (string)call_other( this_object(), parts[0], ob, parts[1], dark);
#else
         switch(parts[0]) {
         case "my_mirror_short":
           desc = my_mirror_short(ob, parts[1]);
           break;
         case "my_a_short":
           desc = my_a_short(ob, parts[1], dark);
           break;
         case "my_the_short":
           desc = my_the_short(ob, parts[1], dark);
           break;
         case "my_one_short":
           desc = my_one_short(ob, parts[1], dark);
           break;
         case "my_poss_short":
           desc = my_poss_short(ob, parts[1], dark);
           break;
         case "my_the_poss_short":
           desc = my_the_poss_short(ob, parts[1], dark);
           break;
         }
#endif
      } else {
         if (sizeof(parts[0])) {
            desc = parts[0];
         } else {
            desc = "something";
         }
      }
      i = member_array(desc, descs_str);
      if (i == -1) {
         descs_str += ({ desc });
         descs_ob += ({ ({ ob }) });
      } else {
         descs_ob[i] += ({ ob });
      }
   }
   i = member_array( "you", descs_str );
   if ( i != -1 && i != sizeof(descs_str) - 1) {
      descs_str = descs_str[0..i-1] + descs_str[i+1..] + ({ "you" });
      descs_ob = descs_ob[0..i-1] +  descs_ob[i+1..] + descs_ob[i..i];
   }
   list = "";
/*
   if (dark) {
     if(sizeof(short_list) > 1) {
        list = "somethings";
     } else {
        if(descs_ob[0] && living(descs_ob[0])) {
           list = "someone";
        } else {
           list = "something";
        }
     }
   } else */ {
      for ( i = 0; i < sizeof( descs_str ); i++ ) {
         things = descs_ob[ i ];
         if ( sizeof( things ) == 1 ) {
            if (exact)  {
               if (things[0]) {
                  list += "one " + things[0]->short();
               } else {
                  list += descs_str[i];
               }
            } else {
               list += descs_str[ i ];
            }
         } else {
            things -= ({ 0 });
            if ( sizeof(things) ) {
               list += evaluate(number, sizeof(things)) + " " +
                     this_object()->get_pretty_plural( things[ 0 ], dark );
            } else {
               list += evaluate(number, sizeof(things)) + " unknown objects";
            }
         }
         if ( i == sizeof( descs_str ) - 1 ) {
            continue;
         }
         if ( i == sizeof( descs_str ) - 2 ) {
            list += " and ";
         } else {
            list += ", ";
         }
      }
   }
   return list;
} /* calc_shorts() */

/**
 * This method handles doing the indenting of the input string, fitting it
 * correctly to the width of the column.
 * @param part the column to do stuff with.
 */
string indent_column(string column, int width, int pad) {
   int left;
   int right;
   int space;
   string *parts;
   string part;
   mixed stuff;
   string ret;

   ret = "";
   if ( column[ 0 .. 2 ] != "$I$" ) {
      column = "$I$0=$C$"+ column;
   }
   parts = explode( column, "$C$" );
   parts = parts[0..0] + map(parts[1..], (: capitalize($1) :));
   parts = explode( implode(parts, ""), "$I$" );
   foreach ( part in parts) {
      sscanf( part, "%s=%s", stuff, part );
      if ( stuff[ 0 ] == ' ' ) {
         space = !space;
      }
      stuff = explode( stuff, "," );
      if ( stuff[ 0 ] != "" ) {
         switch ( stuff[ 0 ][ 0 ] ) {
            case '+' :
               if ( space && ( left > 0 ) && ( part != "" ) ) {
                  part = SPACES[ 0 .. left - 1 ] + part;
               }
               left += to_int( stuff[ 0 ][ 1 .. ] );
               break;
            case '-' :
               left -= to_int( stuff[ 0 ][ 1 .. ] );
               if ( left < 0 ) {
                  left = 0;
               }
               if ( space && ( left > 0 ) && ( part != "" ) ) {
                  part = SPACES[ 0 .. left - 1 ] + part;
               }
               break;
            default :
               left = to_int( stuff[ 0 ] );
         }
      } else {
         left = 0;
      }
      if ( sizeof( stuff ) > 1 ) {
         switch ( stuff[ 1 ][ 0 ] ) {
            case '+' :
               right += to_int( stuff[ 1 ][ 1 .. ] );
               break;
            case '-' :
               right -= to_int( stuff[ 1 ][ 1 .. ] );
               if ( right < 0 )
                  right = 0;
               break;
            default :
               right = to_int( stuff[ 1 ] );
         }
      } else {
         right = 0;
      }
#ifdef DEBUG
      if ( this_object()->query_property( "see eemessages" ) )
         efun::tell_object( this_object(), part +"\n"+
               left +", "+ right +", "+ cols +"\n" );
#endif      
      // Need to change the terminal_colour efun to allow padding.
      if ( left > 0 ) {
         ret += fix_string( part, width - right, left, pad);
      } else {
         ret += fix_string( part, width - right, 0, pad );
      }
   }
   return ret;
}

/**
 * This method fits a message into a the current players screen size.  This
 * does all sorts of other evil stuff too, like handling indenting and
 * all sorts of things!  Most of which I do not understand so I won't
 * say anything about here.  The $C$ does capitalization, $I$<num>=
 * does indenting of all the following lines of <num> spaces.  The
 * message automatically has $I$0=$C$ prepended to the message if it
 * does not start with $I$.  SO if you start a message with $I$ then it
 * will not capitalize the first letter of the message.
 * @param message the message to fit in
 * @return the fitted message
 */
string fit_message( string message ) {
   int i;
   int j;
   int size;
   int width;
   int ok;
   string* columns;
   string num;
   mixed* stuff;
   string ret;

   if ( strlen( message ) < 6 ) {
      return message;
   }
   // The way the columns work, there is a <num>= after the column
   // definition that handles setting how wide the column is, the
   // last column may have the <num> bit blank.
   columns = explode( message, "$COLUMN$" );
   if (sizeof(columns) > 1) {
      stuff = allocate(sizeof(columns), ({ }));
      width = cols;
      for (i = 0; i < sizeof(columns) - 1; i++) {
         if (sscanf(columns[i], "%s=%s", num, columns[i]) == 2) {
            size = to_int(num);
         } else {
            size = 10;
            columns[i] += "\nMust specify a column size.\n";
         }
         width -= size;
         stuff[i] = ({ size }) + explode(indent_column(columns[i], size, 1), "\n");
      }
      stuff[<1] = ({ width }) + explode(indent_column(columns[<1], width, 0), "\n");
      // Now merge them together.
      j = 1;
      ret = "";
      do {
         // Keep going till the bits run out.
         ok = 0;
         for (i = 0; i < sizeof(stuff); i++) {
            if (sizeof(stuff[i]) > j) {
               // Check the colours.
               if (sizeof(stuff[i]) > j + 1) {
                  ok = 1;
               }
               ret += stuff[i][j];
            } else if (i < sizeof(stuff) -1) {
               // Need to pad it out.
               ret += sprintf("%*s ", stuff[i][0] - 1, "");
            }
         }
         j++;
         ret += "\n";
         ret = fix_string(ret);
      } while (ok);
   } else {
      ret = indent_column(columns[0], cols, 0);
   }
   return ret;
} /* fit_message() */

/**
 * This method does any extra mxp processing on the output string
 * so it will work with the client correctly.
 * @param input the input string
 * @return the output string with mangling
 */
string fix_for_mxp(string input) {
    return replace(input, ({
                          "&", "&amp;",
                          "<", "&lt;", ">", "&gt;", 
                          "\n", mxp_next_secure(this_object()) + "<BR>",
                          "MXP&lt;", "<", "MXP&gt;", ">" }));
}

/**
 * This method shows the message to the player.
 * @param message the message to show
 * @see fit_message()
 */
void show_message( string message ) {
   string bit;

   if ( sscanf( message, "$P$%s$P$%s", bit, message ) == 2 ) {
      this_object()->more_string( fit_message( message ), bit, 1 );
   } else {
      // In here we do some mxp processing if need be.
      if (has_mxp(this_object())) {
         efun::tell_object( this_object(), fix_for_mxp( fit_message( message ) ));
      } else {
         efun::tell_object( this_object(), fit_message( message ) );
      }
   }
} /* show_message() */

/**
 * This is the main evaluation routine.  This is the one that
 * co-ordinates the works...  It is used by the print_messages
 * routine to create the message to print out.
 * <p>
 * The input parameter contains two elements, the first is the
 * message and the second is the things array.  This corresponds to
 * the values returned by the fix_message method.
 * @param stuff the message to evaulate
 * @return the nice printed out string
 * @see print_messages()
 */
string evaluate_message( mixed *stuff ) {
   int i;
   string message, start, finish, verb_sing, verb_plur;

   message = stuff[ 0 ];
   clear_event_info_had_shorts();
   for ( i = 0; i < sizeof( stuff[ 1 ] ); i++ ) {
/* Things assume this ordering, so do not change. */
      message = replace_string( message, "$"+ i +"$",
            calc_shorts( stuff[ 1 ][ i ] ) );
      while ( sscanf( message, "%s$V$"+ i +"=%s,%s$V$%s", start, verb_sing,
            verb_plur, finish ) == 4 ) {
         if ( ( sizeof( stuff[ 1 ][ i ] ) == 1 ) &&
               sizeof(_event_info->had_shorts) &&
               objectp( _event_info->had_shorts[ 0 ] ) ) {
            if ( _event_info->had_shorts[ 0 ]->query_property( "group object" ) ||
                  _event_info->had_shorts[ 0 ]->group_object() ) {
               message = sprintf("%s%s%s", start, verb_plur, finish);
            } else {
               message = sprintf("%s%s%s", start, verb_sing, finish);
            }
         } else {
            message = sprintf("%s%s%s", start, verb_plur, finish);
         }
      }
   }
   return message;
} /* evaluate_message() */

/**
 * This prints out the messages after the delay, printing out the
 * messages in a nice cute way.  It still retains the order of the
 * messages though.  This can be forced to occur by a message
 * occuring on the player object which requires something to
 * be printed.
 * @see evaluate_message()
 * @see show_message()
 */
void print_messages() {
   int i;
   string message;
   mixed *messages;

   messages = _event_info->eemessages;
   _event_info->eemessages = ({ });
   for ( i = 0; i < sizeof( messages ); i += 2 ) {
      message = messages[ i ];
      if ( sizeof( messages[ i + 1 ] ) ) {
         message = evaluate_message( ({ message, messages[ i + 1 ] }) );
      }
      show_message( message );
   }
   _event_info->where = 0;
} /* print_messages() */

/**
 * This method will handle doing exciting things to messages and
 * returning them as a usable format.
 * @param message the message to evaluate
 * @return the message in a printable (to the player) format
 * @see evaluate_message()
 */
string convert_message( string message ) {
  if(message)
    message = evaluate_message( reform_message( message, ({ }) ) );
  _event_info->where = 0;
  return message;
} /* convert_message() */

/**
 * This method is called when an inform event is called.
 * @param mess the message to print
 * @param which the type of inform
 * @parm thing the thing associated with the inform
 */
nomask varargs void event_inform( object, mixed mess, string which,
                           object thing ) {
  string *on, inform_col;
  int add_friend_later;

  on = inform_types;
  if (!on) {
     on = ({ });
  }

  if(this_object()->query_property( "inform repressed" ) || !sizeof( on))
      return;
  if(thing && thing->query_creator() && !thing->query_visible(this_object()))
    return;

  if (which == "logon" && is_friend(thing->query_name()) &&
      member_array("friend", on) != -1 ) {
    which = "friend";
  } else if ( ( which == "logon" || which == "link-death" ) &&
      PLAYERINFO_HANDLER->query_alerts_for(thing->query_name()) &&
      member_array("alert", on) != -1 ) {
    which = "alert";
  } else if(member_array(which, on) == -1 ) {
    return;
  }

  if(INFORM_COLOURS[which]) {
    inform_col = colour_event(which, INFORM_COLOURS[which]);
  } else {
    inform_col = colour_event(which, INFORM_COLOURS["default"]);
  }
  
  if(which == "friend") {
    // check for a friend.
    add_friend_later = 0; 
    
    if(!mess) {
      mess = " -- " + query_friend_tag(thing->query_name());
    } else if ( stringp( mess ) ) { 
      mess += " -- " + query_friend_tag(thing->query_name());
    } else { 
      add_friend_later = 1;
    }
    
    if (INFORM_COLOURS["friend"]) {
      inform_col = colour_event(which, INFORM_COLOURS["friend"]);
    }
  }

  if (functionp(mess)) {
    mess = evaluate(mess, this_object());
    
    if ( stringp( mess ) && add_friend_later ) { 
      mess += "%^RESET%^%^" + inform_col + "%^ -- " + 
        query_friend_tag(thing->query_name());
    }
  }

  if(which == "logon" && this_object()->query_lord() &&
     !check_earmuffs("verbose-logon", this_object()) &&
     strsrch(mess, "enters") != -1)
    mess +=  " %^RESET%^%^" + inform_col + "%^" + query_ip_name(thing);

  this_object()->add_message( "[%^"+ inform_col +"%^"+ mess +"%^RESET%^]\n",                              ({ }) );
} /* event_inform() */

/**
 * This method is called when an object leaves or arrives in
 * the room.  It prints out
 * the message, well adds it to the queue of printable messages.
 * @param mess the message to print
 * @param thing the thing which is leaving/arriving
 * @param going if it is going
 */
protected void enter_exit_mess( string mess, object thing, int going ) {
   int i;
   string part, verb, *words;

   mess = replace_string( mess, "$N", "$0$" );
   words = explode( mess, " " );
   for ( i = sizeof( words ) - 1; i > -1; i-- ) {
     /*
      * If $s ends a word, it represents verb conjugation.
      * The test of the following letter is to check that it does end the word.
      */
      if ( ( sscanf( words[ i ], "%s$s%s", verb, part ) == 2 ) &&
            ( ( part[ 0 ] < 97 ) || ( part[ 0 ] > 122 ) ) ) {
         words[ i ] = "$V$0="+ pluralize( verb ) +","+ verb +"$V$"+ part;
      }
      /*
       * If we have %<verb>%, it represents verb conjugation.
       * This is unlikely to get confused with anything else...
       */
      if ( sscanf( words[ i ], "%%%s%%%s", verb, part ) == 3 ) {
         words[ i ] = "$V$0="+ pluralize( verb ) +","+ verb +"$V$"+ part;
      }
   }
   if ( going ) {
      this_object()->add_message( implode( words, " " ) +"\n",
            ({ ({ "my_the_short:"+ file_name( thing ) }) }) );
   } else {
      this_object()->add_message( implode( words, " " ) +"\n",
            ({ ({ "my_a_short:"+ file_name( thing ) }) }) );
   }
} /* enter_exit_mess() */

/**
 * This method is called when an object enters the room.
 * @param thing the thing entering
 * @param mess the message to print on entering
 */
void event_enter( object thing, string mess, object ) {
  if ( !stringp( mess ) )
    return;

  thing->sneak_task(this_object());
  this_object()->perception_task(thing);

  if ( !thing->query_visible( this_object() ) ) {
    return;
  }

  enter_exit_mess( mess, thing, 0 );
  
} /* event_enter() */

/**
 * This method is printed when an object exits the room.
 * @param thing the object exiting
 * @param mess the message to print
 * @param to where the object is going to
 */
void event_exit( object thing, string mess, object to ) {
   ::event_exit( thing, mess, to );
   if ( !stringp( mess ) )
      return;
   if ( !thing->query_visible( this_object() ) )
      return;
   enter_exit_mess( mess, thing, 1 );
} /* event_exit() */

/** @ignore yes */
void event_death( object thing, object *, object killer,
      string room_mess, string killer_mess ) {
   if ( this_object() == thing ) {
      return;
   }

   // Take dead people out of the attacker list
   //this_object()->remove_attacker_list(thing);
   
   if ( ( this_object() == killer ) && stringp( killer_mess ) ) {
      this_object()->add_message( replace( killer_mess, "$D",
            (string)thing->the_short() ), ({ }) );
      print_messages();
      return;
   }
   if ( stringp( room_mess ) ) {
      if ( objectp( killer ) ) {
         this_object()->add_message( replace( room_mess,
               ({ "$D", (string)thing->the_short(),
               "$K", (string)killer->the_short() }) ), ({ }) );
      } else {
         this_object()->add_message( replace( room_mess, "$D",
               (string)thing->the_short() ), ({ }) );
      }
      print_messages();
   }
} /* event_death() */

/**
 * This method is called when the 'say' and 'tell_room' simul_efuns is used.
 * @param caller the object doing the say
 * @param str the message to print
 * @param avoid the people to avoid in the say
 */
void event_say(object caller, string str, mixed avoid, string language) {
  if (pointerp(avoid)) {
    if (member_array(this_object(), avoid) != -1) {
      return ;
    }
  } else if (avoid == this_object()) {
    return ;
  }
  if (language) {
      this_object()->add_message( LANGUAGE_HAND->garble_text_say(str,
                                  language, this_object()), ({ }) );
   } else {
     this_object()->add_message( str, ({ }) );
   }
} /* event_say() */

void event_see( object caller, string words, object thing, mixed avoid ) {
   if ( !thing->query_visible( this_object() ) )
      return;
   event_say( caller, words, avoid, 0 );
} /* event_see() */

/**
 * This method is called by the simul_efun 'write'.
 * @param caller the calling object
 * @param str the string to write, can be a pointer to two strings with a language
 * @param language the language to write with
 */
void event_write(object caller, string str, string language) {
   if (language) {
     this_object()->add_message( LANGUAGE_HAND->garble_text_say(str,
                                    language, this_object()), ({ }) );
   } else {
      this_object()->add_message( str, ({ }) );
   }
   print_messages();
} /* event_write() */

/** @ignore yes */
void do_efun_write( string str, string language ) {
   event_write( 0, str, language );
}

/**
 * This method is called by the soul to print out the soul messages.
 * @param ob the object doing the soul
 * @param str the string to print
 * @param avoid the people not to print the message to
 */
varargs void event_soul(object ob, string str, mixed avoid) {
  //str = replace(str, "%^", " ");
  if (ob != this_object()) {
    if (strsrch(str, "%^") != -1) {
      if (!query_property(PLAYER_ALLOW_COLOURED_SOULS)) {
         str = strip_colours(str);
      }
    }

    if (sizeof(avoid) > 1 && check_earmuffs("multiple-soul", ob)) {
      return ;
    }
    event_say(ob, colour_event("soul", "") + "$C$" + str + "%^RESET%^", avoid, 0);
  } else {
    event_write( ob, str + "%^RESET%^", 0 );
  }
} /* event_soul() */

/**
 * This method is called when someone does an emote.
 * @param thing the object doing the emote
 * @param mess the emote to print
 */
void event_emote( object thing, string mess ) {
   if ( thing == this_object() )
      return;
   this_object()->add_message( colour_event("emote", "%^CYAN%^") + mess + "%^RESET%^", ({ }) );
} /* event_emote() */

/**
 * This method is called when someone says something.
 * @param ob the object doing the say
 * @param start the start message
 * @param mess the message to say
 * @param lang the language it is printed in
 * @param accent the accent object to use
 */
void event_person_say(object ob, string start, string mess, string lang,
                      string accent) {
   string *args, astr, tstr;
   int mangle_accent;

   if(ob == this_object() )
      return;

   if (accent) {
      if (query_nationality_accent_ob() != accent) {
         if (query_mangle_accent()) {
            mangle_accent = 2;
         } else {
            mangle_accent = 1;
         }
      }
   }

   if((lang != query_default_language() && lang != "general") ||
       (accent && mangle_accent == 1)) {

     tstr = start[0..<3];
     if(lang != query_default_language() && lang != "general")
       tstr += " in " + cap_words(lang);

     if(accent && mangle_accent == 1) {
       astr = accent->query_accent_name();
       if(astr[0] == 'a' || astr[0] == 'e' || astr[0] == 'i' ||
          astr[0] == 'o' || astr[0] == 'u')
         astr = "an " + astr;
       else
         astr = "a " + astr;
       
       tstr += " with " + astr + " accent";
     }
     start = tstr + ": ";
   }

   if(this_object()->query_property(SHORTHAND_OUTPUT_PROP)) {
     mess = LANGUAGES->fix_shorthand(mess);
   }

   args = LANGUAGE_HAND->garble_say(lang, start, mess, this_object(),
                                    ob, SAY_TYPE);
   start = args[ 0 ];
   mess = args[ 1 ];

   if (accent && mangle_accent == 2) {
      mess = accent->garble_say(mess, this_object(), ob, SAY_TYPE,
                                query_default_language());
   }
   
   this_object()->add_message( "$I$5=" + colour_event("say", "%^CYAN%^") +
                               "$C$"+ start +
                               mess +"%^RESET%^\n",
             ({ }) );
} /* event_person_say() */

/**
 * @ignore yes
 * Use this on pain of death :)
 */
void add_tell_history(string start, string mess, int remote) {
  if (!pointerp(tell_history)) {
    tell_history = ({ });
  }
  tell_history +=  ({ ({ start, mess, time(), remote }) });
  if (sizeof(tell_history) > MAX_TELL_HIS) {
    tell_history = tell_history[1..];
  }
} /* add_tell_history() */

/* Modification by Pinkfish 8th of August 1995
 * on Grampa's request to remove the nomask.
 */
/**
 * This method is called when a person is told something.
 * @param ob the object doing the tell
 * @param start the start bit of the message
 * @param mess the message itself
 * @param lang the language it was spoken in
 */
/* nomask */ void event_person_tell( object ob, string start, string mess) {
   int id;
   string *args;
   string tmp;
   
   if ( this_object()->query_property( "ignoring" ) ) {
      if ( member_array( (string)ob->query_name(), 
           (string *)this_object()->query_property( "ignoring" ) ) != -1 &&
           !ob->query_creator()) {
         tell_object(ob,this_object()->query_name()+" is ignoring you and "
                     "will not have heard what you said.\n");
         return;
      }
   }

   if(this_object()->query_property(SHORTHAND_OUTPUT_PROP))
     mess = LANGUAGES->fix_shorthand(mess);

   if (_event_info->busy && (!pointerp(_event_info->busy) ||
                             member_array(ob, _event_info->busy) == -1)) {
     tell_object(ob, this_object()->query_cap_name() +
                  " is currently busy with "
                  "someone else, " + this_object()->query_pronoun() + 
                  " has heard this message and will get back to "
                  "you shortly.\n");
      start = "[BUSY] " + start;
   }

   add_tell_history(start, mess, 0);
   tmp = fix_string(replace(colour_event("tell", "%^YELLOW%^"),
                                         "%^", "%%^") +
                                 "%s%s%%^RESET%%^\n",
                                 cols, 5, 0, capitalize(start), mess);
   if (has_mxp(this_object())) {
      efun::tell_object(this_object(), fix_for_mxp(tmp));
   } else {
      efun::tell_object(this_object(), tmp);
   }
   if (userp(this_object()) &&  interactive( this_object() ) &&
      (id = query_idle(this_object())) > TELL_WARN_TIME) {
     args = ({ });
     if (id/(60*60))
        args += ({ (id/(60*60))+" hours" });
     if ((id/60)%60)
        args += ({ ((id/60)%60)+" minutes" });
     if (id%60)
        args += ({ (id%60)+" seconds" });
     write(this_object()->query_name()+" has been idle for "+
           query_multiple_short(args)+".\n");
   }

   if ( this_object()->query_property( PASSED_OUT ) ) {
      write( "Something tells you that $C$"+
            (string)this_object()->query_name() +
            " will be unable to reply to you just yet.\n" );
   }
} /* event_person_tell() */

/**
 * This method is called when the whisper even is generated.
 * @param ob the object whispering
 * @param start the start of the whisper message
 * @param mess the message to print
 * @param obs the objects to tell the message to
 * @param lang the lanaguage the whisper is in
 * @param me the object doing the whispering
 */
void event_whisper(object ob, string start, string mess,
                   object *obs, string lang, object me) {
   string blue;
   string *args;

   blue = "";
   if (me == this_object())
      return;

   if (lang != query_default_language() && lang != "general")
     blue = " in " + cap_words(lang);
   
   if(this_object()->query_property(SHORTHAND_OUTPUT_PROP))
     mess = LANGUAGES->fix_shorthand(mess);

   if ( member_array( this_object(), obs ) == -1)  {
      if(ob->query_visible(this_object()))
         this_object()->add_message( "$I$5=" +
                                   colour_event("whisper", "%^CYAN%^") + "$C$"+
                                   start +
                                   query_multiple_short( obs ) +
                                   ".%^RESET%^\n", ({ }) );
   } else {
      args = LANGUAGE_HAND->garble_say(lang, start, mess, this_object(),
                                    ob, WHISPER_TYPE);
      start = args[ 0 ];
      mess = args[ 1 ];

      if ( sizeof( obs ) == 1 ) {
         this_object()->add_message( "$I$5=" +
                                     colour_event("whisper", "%^CYAN%^") +
                                     "$C$"+ start +"you"+
                                     blue +": "+ mess +"%^RESET%^\n", ({ }) );
      } else {
         this_object()->add_message( "$I$5=" +
                                     colour_event("whisper", "%^CYAN%^") +
                                     "$C$"+ start +
                                     query_multiple_short( obs ) + blue +": " +
                                     mess +"%^RESET%^\n",
                                     ({ }) );
      }
   }
} /* event_whisper() */

/**
 * This method is generated when a shout is done by a player.
 * @param thing the thing doing the shout
 * @param start the start string to print
 * @param mess the message to print
 * @param lang the language the shout is in
 * @param co_ord the co-ordinate of the shouter
 * @param range the range of the shout
 */
void event_person_shout( object thing, string start, string mess, string lang,
      int *co_ord, int range ) {
   /*string garbler; */
   mixed *args;

   if ( this_object() == this_player() ) {
      return;
   }
   if ( check_earmuffs( "shout", thing ) ) {
      return;
   }
   if ( !environment() ) {
      return;
   }
   if ( environment()->query_property( "shout zone" ) !=
        environment( this_player() )->query_property( "shout zone" ) ) {
      return;
   }

   if (lang != query_default_language() && lang != "general") {
      start += " in " + capitalize(lang);
   }

   //
   // Put in a check so you don't see shouts from people you are
   // ignoring.
   //
   if (sizeof(query_ignoring(({ this_player() }))) ) {
      return ;
   }

   args = LANGUAGE_HAND->garble_say(lang, start, mess, this_object(),
                                    thing, SHOUT_TYPE);
   start = args[ 0 ];
   mess = args[ 1 ];
   if(this_object()->query_property(SHORTHAND_OUTPUT_PROP))
     mess = LANGUAGES->fix_shorthand(mess);

   if ( environment() == environment( this_player() ) ) {
      this_object()->add_message( "$I$5=" + colour_event("shout", "") + "$C$"+
                                  start +": "+ mess +"%^RESET%^\n", ({ }) );
      return;
   }
   if ( sizeof( co_ord ) != 3 ) {
      return;
   }
   BROADCASTER->broadcast_event( ({ this_object() }), co_ord, start +
      ": "+ mess, range, 1, 0 );
} /* event_person_shout() */

/**
 * This event is generated when a newbie chat event is done.
 * @param thing the thing generateing the newbie chat
 * @param message the message the newbie said
 */
void event_newbie(object thing, string message) {
  string tmp;

  if((this_player() == this_object() ) ||
     check_earmuffs("newbie", this_player())) {
    return;
  }
  
  if (sizeof(query_ignoring(({ this_player() }))) ) {
    return ;
  }
  
  if(this_object()->query_property(SHORTHAND_OUTPUT_PROP))
    message = LANGUAGES->fix_shorthand(message);
   
  tmp = fix_string(replace(colour_event("newbie", "%^MAGENTA%^"),
                                       "%^", "%%^") +
                               "(newbie)%%^RESET%%^ %s\n",
                               cols, 5, 0, message);
  if (has_mxp(this_object())) {
     efun::tell_object(this_object(), fix_for_mxp(tmp));
  } else {
     efun::tell_object(this_object(), tmp);
  }
}

/**
 * This event is generated when a newbiehelpers chat event is done.
 * @param thing the thing generateing the newbiehelpers chat
 * @param message the message the newbiehelper said
 */
void event_newbiehelpers(object thing, string message) {
  string tmp;

  if((this_player() == this_object() ) ||
     check_earmuffs("newbiehelpers", this_player()) ||
     !NEWBIEHELPERS_HANDLER->query_helper_access(this_object())) {
    return 0;
  }
  
  if (sizeof(query_ignoring(({ this_player() }))) ) {
    return 0;
  }
  
  if(this_object()->query_property(SHORTHAND_OUTPUT_PROP))
    message = LANGUAGES->fix_shorthand(message);
  
  tmp = fix_string(replace(colour_event("newbiehelpers", 
                                  "%^YELLOW%^"), "%^", "%%^") +
                               "(newbiehelpers)%%^RESET%%^ %s\n",
                               cols, 5, 0, message);
  if (has_mxp(this_object())) {
     efun::tell_object(this_object(), fix_for_mxp(tmp));
  } else {
     efun::tell_object(this_object(), tmp);
  }
}

/**
 * This event is generated when a combat message occurs.
 * @param thing the thing generateing the event.
 * @param message the message to be displayed.
 * @param exclude objects not to show this message to.
 * @param verbose is the message considered verbose?
 */
void event_combat(object thing, string message, object *exclude, int verbose) {
  if(member_array(this_object(), exclude) != -1)
    return;

  if(verbose && !this_object()->query_verbose("combat"))
    return;
  
  this_object()->add_message(colour_event("combat", "%^WHITE%^") + "$C$" + 
                             message + "%^RESET%^", ({ }));
  this_object()->print_messages();
}

/**
 * This event is generated when a creator tell is done.
 * @param ob the object generating the event
 * @param start the start bit
 * @param mess the message bit
 * @param forced if it is forced to occur
 * @param channel the creator channel to talk on
 */
nomask void event_creator_tell(object ob, string start, string mess,
                               int forced, string channel) {
  string tmp;
  
  if (!channel)
    channel = "cre";
  
  if (ob == this_object() ||
      ((sizeof(this_object()->query_ignoring( ({ ob }) ) ) || 
        check_earmuffs( channel, ob )) && !forced) ||
      !this_object()->query_creator()) {
    return;
  }
  // Permissions checks.
  if(member_array(channel, this_object()->channel_list()) == -1)
    return;
       
  if(this_object()->query_property(SHORTHAND_OUTPUT_PROP))
    mess = LANGUAGES->fix_shorthand(mess);
 
  tmp = fix_string(replace(colour_event(channel, "%^CYAN%^"),
                                       "%^", "%%^") +
                               "(" + channel + ") %s%s%%^RESET%%^\n",
                               cols, 5, 0, start, mess);
  if (has_mxp(this_object())) {
     efun::tell_object(this_object(), fix_for_mxp(tmp));
  } else {
     efun::tell_object(this_object(), tmp);
  }
}

/**
 * This event is generated when a lord tell is done.
 * @param ob the object generating the event
 * @param start the start bit
 * @param mess the message bit
 * @param forced if it is forced to occur
 */
nomask void event_lord_tell( object ob, string start, string mess,
      int forced ) {
  string tmp;

  if ( this_player() == this_object() ) {
      HIST_HANDLER->add_lord_history(start, mess);
      return;
   }
  if (ob == this_object()
     || (check_earmuffs("lord", ob) && !forced) ||
      !master()->query_lord((string)this_object()->query_name()))
    return;

  if(this_object()->query_property(SHORTHAND_OUTPUT_PROP))
     mess = LANGUAGES->fix_shorthand(mess);

  tmp = fix_string(replace(colour_event("lord", "%^YELLOW%^"),
                                       "%^", "%%^") +
                               "(lord) %s%s%%^RESET%%^\n",
                               cols, 5, 0, start, mess);
  if (has_mxp(this_object())) {
     efun::tell_object(this_object(), fix_for_mxp(tmp));
  } else {
     efun::tell_object(this_object(), tmp);
  }
} /* event_lord_tell() */

/**
 * This event is generated when a intermud creator tell is done.
 * @param ob the object generating the event
 * @param mname the name of the mud
 * @param pname the name of the player
 * @param mess the message
 * @param ig the ignore object
 * @param emote if it is an emote
 */
void event_inter_creator_tell(object ob, string mname, string pname, 
                              string mess, object ig, int emote) {
   string tmp;

  if (!this_object()->query_creator() || check_earmuffs("inter-creator-tell", 0)
      || this_object() == ig)
    return ;
   tmp = fix_string("%s@%s%s%s\n", cols, strlen(mname) + strlen(pname) + 3,
                      0, pname, mname, (emote?" ":": "), mess);
  if (has_mxp(this_object())) {
     efun::tell_object(this_object(), fix_for_mxp(tmp));
  } else {
     efun::tell_object(this_object(), tmp);
  }
} /* event_inter_creator_tell() */

/**
 * This event is generated when a creator tell is done.
 * @param ob the object generating the event
 * @param mname the name of the mud
 * @param pname the name of the player
 * @param mess the message
 * @param ig the ignore object
 * @param emote if it is an emote
 */
void event_intermud_tell(object ob, string start, string mess,
                         string channel, object ig) {
  string tmp;

  if (!this_object()->query_creator() || check_earmuffs("intermud-all", 0)
      || check_earmuffs(channel, 0) || this_object() == ig) {
    return ;
  }
  tmp = fix_string("%%^MAGENTA%%^(%s)%%^RESET%%^ %s%s\n", cols,
                      strlen(start)+ strlen(channel)+ 3, 0, channel, start,
                      mess);
  if (has_mxp(this_object())) {
     efun::tell_object(this_object(), fix_for_mxp(tmp));
  } else {
     efun::tell_object(this_object(), tmp);
  }
} /* event_intermud_tell() */

/**
 * This method is called when an echo to is generated by the player.
 * @param ob the object doing the echo to
 * @param mess the message being printed
 * @param me the person generating the echo to
 */
void event_player_echo_to(object ob, string mess, object me) {
  if ( master()->query_lord( (string)this_object()->query_name() ) )
     this_object()->add_message( "$0$ echos to you:\n", ({ ({ "my_the_short:"+
            file_name( me ) }) }) );
   this_object()->add_message( colour_event("echo", "") + mess + "%^RESET%^",
                               ({ }) );
} /* event_player_echo_to() */

/**
 * This method is called when an emoteall is generated by a player.
 * @param ob the object doing the emoteall
 * @param mess the message being printed
 */
void event_player_emote_all(object ob, string mess) {
  if (ob == this_object()) {
    return;
  }

  if ( master()->query_lord( (string)this_object()->query_name() ) ) {
     this_object()->add_message( "$0$ emotes to all:\n", ({ ({ "my_the_short:"+
            file_name( ob ) }) }) );
  }

  mess = this_object()->colour_event( "emoteall" ) + mess + "%^RESET%^"; 
  
  this_object()->add_message( "$I$5=$C$"+ replace_string( mess, "$N", "$0$" ),
    ({ ({ "my_the_short:"+ file_name( ob ) }) }) );
} /* event_player_emote_all() */

/**
 * This method is called when an echo is generated by a player.
 * @param ob the object doing the echo
 * @param mess the message being printed
 */
void event_player_echo(object ob, string mess) {
   if (ob == this_object()) {
      return;
   }
   if ( master()->query_lord( (string)this_object()->query_name() ) ) {
      this_object()->add_message( "$0$ echos:\n", ({ ({ "my_the_short:"+
            file_name( ob ) }) }) );
   }
   this_object()->add_message( mess, ({ }) );
} /* event_player_echo() */

/**
 * This method is generated internally by the driver when this player is
 * snooping someone else.
 * @param mess the snoop message
 */
void receive_snoop(string mess) {
  tell_object(this_object(), "] "+mess);
} /* receive_snoop() */

/**
 * This is a call back generated by the driver internally to tell us about
 * terminal types.
 * @param type the terminal type returned
 */
void terminal_type(string type) {
  if (set_network_terminal_type(type)) {
    tell_object(this_object(), "Setting your network terminal type to \""+
                type+"\".\n");
  } else {
    if (term_name == "network") {
      if (!_event_info->last_term || _event_info->last_term != type) {
        _event_info->last_term = type;
/* Keep going until they repeat twice.  This is the end of the list. */
        printf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE);
      } else
        tell_object(this_object(), "Unknown terminal type \""+type+"\".\n");
    }
  }
} /* terminal_type() */

/**
 * This is a call back generated by the driver internally to tell us about
 * the window size of the remote machine.  This information in this is
 * only used if the terminal is a network type.
 * @param width the number of columns
 * @param height the number of rows
 */
void window_size(int width, int height) {
  if (term_name == "network") {
    if (width > 10 && width < 256) {
      set_cols(width);
   }
   if (height > 5 && height < 256) {
      set_rows(height);
   }
   tell_object(this_object(), "Your machine told our machine that your "
               "terminal has "+height+" rows and "+width+" columns.\n");
  }
} /* window_size() */

/**
 * This is a callback generated by the driver to deal with mxp related
 * stuff.
 */
void mxp_enable() {
   // Send down some code to turn on the suboption
   efun::tell_object(this_object(),
               sprintf("%c%c%c%c%c%c", IAC, SB, TELOPT_MXP, IAC, SE, 0) +
               sprintf("%c[1z", 27) +
               replace_string(read_file("/doc/login/mxp_setup"), "\n", "") + "\n");
}