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/
/*   -*- LPC -*-   */
/*
 * $Locker:  $
 * $Id: pattern_compiler.c,v 1.10 2000/11/22 08:30:15 ceres Exp $
 */
/**
 * Compiles up the patterns for use by the add_command system.
 * @see /global/new_parse->add_command()
 * @author Pinkfish
 * @change 29-Jul-97, Jeremy
 *         changed default search order to ME-HERE, since
 *         this is what the "look" and "locate" commands use.
 */
#include <user_parser.h>

#define PATTERN_CACHE_SIZE 200

nosave mapping patterns;
nosave mapping pattern_short;
nosave string *pattern_order;
nosave int hits, reqs, cache_callout;

nomask mixed *compile_pattern(string str);

void create() {
   patterns = ([ "" : ({ 100 }) ]);
   pattern_short = ([ "" : "" ]);
   //pattern_order = ({ });
} /* create() */

void clean_cache() {
  int i;

  for(i=0; i<(sizeof(pattern_order)-PATTERN_CACHE_SIZE); i++) {
    map_delete(patterns, pattern_order[i]);
    map_delete(pattern_short, pattern_order[i]);
  }
  pattern_order = pattern_order[i..];
  cache_callout = 0;
}

/**
 * Returns the compiled pattern to the caller.   This checks to see if they
 * pattern is in its internal cache and if it is, it uses that.
 * @param pattern the pattern to compiler
 * @return the compiler pattern
 * @see /include/user_parser.h
 */
nomask mixed *query_pattern(string pattern) {
  if (!patterns[pattern]) {
    patterns[pattern] = compile_pattern(pattern);
  }
  /*
    else
    hits++;
  pattern_order -= ({ pattern });
  pattern_order += ({ pattern });
  if(!cache_callout && (sizeof(pattern_order) > PATTERN_CACHE_SIZE))
    cache_callout = call_out("clean_cache", 300);
  reqs++;
  */
  return patterns[pattern];
} /* query_pattern() */

/**
 * Compiles the pattern.   Does no cache checking.  This returns
 * only the compiled pattern, it also creates the short pattern as a
 * side effect.  The short pattern can be queried by using
 * query_short_pattern()
 * @param str the pattern to compile
 * @return the compiled pattern
 * @see /include/user_parser.h
 * @see query_short_pattern()
 * @see /global/new_parse.c
 */
nomask mixed *compile_pattern(string str) {
   mixed *pattern;
   mixed *bits;
   int i;
   int failed;
   int type;
   int weight;
   mixed env;
   string short;
   string short_bit;
   int pos;
   int pos2;
   int j;
   int k;

   bits = explode(str, " ") - ({ 0, "" });
   pattern = ({ });
   short = "";
   for (i = 0; i < sizeof(bits) && !failed; i++) {
      switch (bits[i][0]) {
      case '<' :
         pos = strsrch(bits[i], "'");
         if (pos != -1) {
             // Try to find the next one...
             pos2 = strsrch(bits[i][pos + 1..], "'", pos + 1);
             if (pos2 == -1) {
                /* Oh dear...  Look for it man! */
                for (j = i + 1; j < sizeof(bits); j++) {
                   pos2 = strsrch(bits[j], "'");
                   if (pos2 != -1) {
                      break;
                   }
                }
                if (j < sizeof(bits)) {
                   // Ok, found the dreadful thing.
                   for (k = i + 1; k <= j; k++) {
                      bits[i] += " " + bits[k];
                   }
                   // Nip up to the new one.
                   bits[j] = bits[i];
                   i = j;
                   pos2 = strsrch(bits[i], "'", -1);
                }
             } else {
                pos2 += pos + 1;
             }
             // We have it!  Cut out chunks.
             if (pos2 != -1) {
                short_bit = bits[i][pos+1..pos2-1];
                bits[i] = bits[i][0..pos-1] + bits[i][pos2+1..];
             } else {
                short_bit = 0;
             }
         } else {
             short_bit = 0;
         }
         bits[i] = bits[i][1..<2];
         bits[i] = explode(bits[i], ":");
         if (!bits[i]) {
            bits[i] = ({ "" });
         }
         switch (bits[i][0]) {
         case "direct" :
            weight += 7;
            if (sizeof(bits[i]) > 1) {
               switch (bits[i][1]) {
               case "living" :
                  type = LIVING;
                  break;
               case "distant-living" :
                  type = DISTANT_LIVING;
                  break;
               case "any-living" :
                  type = ANY_LIVING;
                  break;
               case "object" :
                  type = ANY_OBJECT;
                  break;
               case "player" :
                  type = TARGET_PLAYER;
                  break;
               default :
                  failed = 1;
                  printf("Unknown type of direct (%s).\n", bits[i][1]);
                  break;
               }
               if (!short_bit) {
                   short += "<"+bits[i][1]+"> ";
               } else {
                   short += "<" + short_bit + "> ";
               }
            } else {
               type = ANY_OBJECT;
               bits[i] += ({ "object" });
               if (!short_bit) {
                  short += "<object> ";
               } else {
                   short += "<" + short_bit + "> ";
               }
            }
            //env = ENV_HERE_ME;
            env = ENV_ME_HERE;
            if (sizeof(bits[i]) > 2)
               switch (bits[i][2]) {
               case "here" :
                  env = ENV_HERE;
                  break;
               case "me" :
                  env = ENV_ME;
                  break;
               case "direct-obs" :
                  env = ENV_DIRECT_OBS;
                  break;
               case "me-here" :
                  env = ENV_ME_HERE;
                  break;
               case "here-me" :
                  env = ENV_HERE_ME;
                  break;
               default :
                  env = bits[i][2];
                  break;
               }
            pattern += ({ DIRECT_OBJECT, type, env });
            break;
         case "indirect" :
            weight += 7;
            if (sizeof(bits[i]) > 1) {
               switch (bits[i][1]) {
               case "living" :
                  type = LIVING;
                  break;
               case "distant-living" :
                  type = DISTANT_LIVING;
                  break;
               case "any-living" :
                  type = ANY_LIVING;
                  break;
               case "object" :
                  type = ANY_OBJECT;
                  break;
               case "player" :
                  type = TARGET_PLAYER;
                  break;
               case "wiz-present" :
                  type = WIZ_PRESENT_TARGET;
                  break;
               default :
                  failed = 1;
                  printf("Unknown type of indirect (%s).\n", bits[i][1]);
                  break;
               }
               if (!short_bit) {
                  short += "<"+bits[i][1]+"> ";
               } else {
                   short += "<" + short_bit + "> ";
               }
            } else {
               type = ANY_OBJECT;
               bits[i] += ({ "object" });
               if (!short_bit) {
                  short += "<object> ";
               } else {
                   short += "<" + short_bit + "> ";
               }
            }
            //env = ENV_HERE_ME;
            env = ENV_ME_HERE;
            if (sizeof(bits[i]) > 2)
               switch (bits[i][2]) {
               case "here" :
                  env = ENV_HERE;
                  break;
               case "me" :
                  env = ENV_ME;
                  break;
               case "direct-obs" :
                  env = ENV_DIRECT_OBS;
                  break;
               case "me-here" :
                  env = ENV_ME_HERE;
                  break;
               case "here-me" :
                  env = ENV_HERE_ME;
                  break;
               default :
                  env = bits[i][2];
                  break;
               }
            pattern += ({ INDIRECT_OBJECT, type, env });
            break;
         case "string" :
            if (sizeof(bits[i]) > 1) {
               switch (bits[i][1]) {
               case "small" :
                  if (!short_bit) {
                     short += "<string> ";
                  } else {
                     short += "<" + short_bit + "> ";
                  }
                  weight += 6;
                  pattern += ({ SHORT_STRING });
                  break;
               case "long" :
                  if (!short_bit) {
                     short += "<string> ";
                  } else {
                     short += "<" + short_bit + "> ";
                  }
                  weight += 5;
                  pattern += ({ STRING });
                  break;
               case "quoted" :
                  if (!short_bit) {
                     short += "\"<string>\" ";
                  } else {
                     short += "\"<" + short_bit + ">\" ";
                  }
                  weight += 8;
                  pattern += ({ QUOTED_STRING });
                  break;
               default :
                  printf("Invalid type of string (%s).\n", bits[i][1]);
                  failed = 1;
                  break;
               }
            } else {
               if (!short_bit) {
                  short += "<string> ";
               } else {
                  short += "<" + short_bit + "> ";
               }
               weight += 5;
               pattern += ({ STRING });
            }
            break;
         case   "number" :
            if (!short_bit) {
               short += "<number> ";
            } else {
               short += "<" + short_bit + "> ";
            }
            weight += 10;
            pattern += ({ NUMBER });
            break;
         case "word" :
            if (!short_bit) {
               short += "<word> ";
            } else {
               short += "<" + short_bit + "> ";
            }
            weight += 7;
            pattern += ({ SINGLE_WORD });
            break;
         case "fraction" :
            if (!short_bit) {
               short += "<fraction> ";
            } else {
               short += "<" + short_bit + "> ";
            }
            weight += 10;
            pattern += ({ FRACTION });
            break;
         default :
            /* Only allows for made up word lists. */
            weight += 10;
            bits[i] = implode(bits[i], ":");
            if (master()->query_word_list(bits[i]) 
                  || this_player()->query_word_list(bits[i])) {
               if (!short_bit) {
                  short += "<"+bits[i]+"> ";
               } else {
                  short += "<" + short_bit + "> ";
               }
               pattern += ({ WORD_LIST, bits[i] });
            } else {
               printf("Unknown word list name (%s)\n", bits[i]);
               failed = 1;
            }
            /*
               else
               pattern += ({ WORD_LIST, explode(bits[i], "|") });
               */
            break;
         }
         break;
      case '{' :
         weight += 10;
         if (bits[i][<1] == '}') {
            pattern += ({ WORD_LIST, explode(bits[i][1..<2], "|") });
            short += bits[i]+" ";
         } else {
            int old = i;
            string elm, *res;

            for (++i; bits[i][<1] != '}'; i++);
            res = ({});
            foreach (elm in explode(implode(bits[old..i], " ")[1..<2], "|"))
               res += ({ explode(elm, " ") });
            pattern += ({ WORD_LIST_SPACES, res });
            short += implode(bits[old..i], " ")+" ";
         }
         break;
      case '[' :
         weight += 4;
         if (bits[i][1] == '<') {
            /* This is a possible wombat.   Hmm, what do we allow inside here? */
            /* For now don't allow things which have a return value */
            if (MASTER->query_word_list(bits[i][2..<3])
                  || this_player()->query_word_list(bits[i][2..<3]))
               pattern += ({ OPTIONAL, bits[i][2..<3] });
            else {                
               printf("Unknown word list name (%s)\n", bits[i]);
               failed = 1;
               pattern += ({ OPTIONAL, bits[i][2..<3] });
            }
            short += bits[i]+" ";
         } else if (bits[i][1] == '{') {
            if (bits[i][<1] == ']') {
               pattern += ({ OPTIONAL, explode(bits[i][2..<3], "|") });
               short += bits[i]+" ";
            } else {
               int old = i;
               string elm, *res;

               for (++i; bits[i][<1] != ']'; i++);
               res = ({});
               foreach (elm in explode(implode(bits[old..i], " ")[2..<3], "|"))
                  res += ({ explode(elm, " ") });
               pattern += ({ OPTIONAL_SPACES, res });
               short += implode(bits[old..i], " ")+" ";
            }
         } else if (bits[i][<1] == ']') {
            pattern += ({ OPTIONAL, explode(bits[i][1..<2], "|") });
            short += bits[i]+" ";
         } else {
            int old = i;
            string elm, *res;

            for (++i; bits[i][<1] != ']'; i++);
            res = ({});
            foreach (elm in explode(implode(bits[old..i], " ")[1..<2], "|"))
               res += ({ explode(elm, " ") });
            pattern += ({ OPTIONAL_SPACES, res });
            short += implode(bits[old..i], " ")+" ";
         }
         break;
      default :
         /* This is one of the few allowable things to stop a variable size 
             argument if they do not put {}'s around it.   It is as-is */
         weight += 10;
         short += bits[i]+" ";
         pattern += ({ WORD_LIST, ({ bits[i] }) });
         break;
      } /* switch() */
   } /* for() */
   if (failed) {
      return 0;
   }
   pattern_short[str] = short;
   return ({ weight }) + pattern;
} /* compile_pattern() */

/**
 * Returns the short pattern for the given pattern string.   The short pattern
 * is the message which is shown to the players.
 * @param str the pattern to get the short for
 * @return the short pattern
 */
string query_short_pattern(string str) {

  reqs++;
  if(!pattern_short[str])
    compile_pattern(str);
  else
    hits++;
  
  return pattern_short[str];
} /* query_short_pattern() */

mixed *stats() {
  return  ({
    ({ "patterns", sizeof(keys(pattern_short)), }),
        ({ "requests", reqs, }),
          ({ "cache hit percent", (hits * 100) / reqs, }),
            });
}