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