lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
/* Do not remove the headers from this file! see /USAGE for more info. */

/* Spell Daemon -- keep track of what spells are valid...
**
** This currently keeps track of the dirs that hold spells and the spells
** contained in those dirs.
**
** Rust @ lima.mudlib.org
*/

#include <assert.h>
#include <security.h>
#include <commands.h>

inherit M_DAEMON_DATA;

#define PRIV_REQUIRED	"Mudlib:daemons"

// Save this....
private string array  spell_dirs = ({});

// Map the name of the spell to its object name.
// We build this each create.
private nosave mapping spell_table = ([ ]);

void add_spell_dir(string dir)
{
  if ( !check_privilege(PRIV_REQUIRED) )
    return;

  ENSURE(dir && is_directory(dir));
  ENSURE(member_array(dir, spell_dirs) == -1);
    
  if ( dir[<1] != '/' )
    dir += "/";

  spell_dirs += ({ dir });
  save_me();
}

void remove_spell_dir(string dir)
{
  if ( !check_privilege(PRIV_REQUIRED) )
    return;

  ENSURE(dir && member_array(dir, spell_dirs) != -1);
  spell_dirs -= ({ dir });
  save_me();
}  

// We need to do this due to parser limitations.
private int valid_spell_name(string spell_name)
{
  return stringp(spell_name) && regexp(spell_name, "^[a-zA-Z0-9 '-]+$");
}

private void build_spell_table()
{
  string * bad_dirs = ({ });

// Not necessary, and would be a bad thing if we didn't rebuild the spell
// table each time.
  spell_dirs -= ({ 0 }); 

  foreach ( string dir in spell_dirs )
  {
    if ( !is_directory(dir) )
    {
 // Dir has been removed
      bad_dirs += ({ dir });
      continue;
    }

    foreach ( string file in get_dir(dir + "*.c") )
    {
      string obname = dir + file[0..<3];
      string spell_name;

      if ( catch(spell_name = obname->get_spell_name()) )
        continue;

      if ( !valid_spell_name(spell_name) )
      {
// log it...
        continue;
      }
      if ( spell_table[spell_name] )
      {
// log it....
        continue;
      }
      spell_table[spell_name] = obname;
    }
  }

  if ( sizeof(bad_dirs) )
  {
    spell_dirs -= bad_dirs;
    save_me();
  }
}

string get_spell_obname(string spell_name)
{
  return spell_table[spell_name];
}

void create()
{
  ::create();
  build_spell_table();
}

/* strip leading "the/a/an"; strip trailing "spell" */
private nomask string find_spell_obname(string spell)
{
  string array parts = explode(spell, " ");
  
  if ( sizeof(parts) > 1 )
  {
    switch ( parts[0] )
    {
      case "the":
      case "a":
      case "an":
        parts = parts[1..];
        break;
	    
      default:
        break;
    }
  }
  if ( sizeof(parts) > 1 && parts[<1] == "spell" )
    parts = parts[0..<2];

  return spell_table[implode(parts, " ")];
}

varargs mixed check_valid_spell(string spell, int has_target, int has_reagent)
{
  string	spell_obname;

  ENSURE(previous_object() == find_object(VERB_OB_CAST));
  
  spell_obname = find_spell_obname(spell);
  if ( !spell_obname )
    return "You know of no such spell.\n";
  
  return spell_obname->_check_valid_spell(has_target, has_reagent);
}

varargs mixed check_valid_target(string spell,
				 object target, mixed has_reagent)
{
  string	spell_obname;

  ENSURE(previous_object() == find_object(VERB_OB_CAST));
  
  spell_obname = find_spell_obname(spell);
  if ( !spell_obname )
    return "You know of no such spell.\n";
  
  return spell_obname->_check_valid_target(target, has_reagent);
}

varargs mixed check_valid_reagent(string spell,
				  object reagent, mixed has_target)
{
  string	spell_obname;

  ENSURE(previous_object() == find_object(VERB_OB_CAST));
  
  spell_obname = find_spell_obname(spell);
  if ( !spell_obname )
    return "You know of no such spell.\n";
  
  return spell_obname->_check_valid_reagent(reagent, has_target);
}

varargs void cast_spell(string spell, object target, object reagent)
{
  string 	spell_obname;

  ENSURE(previous_object() == find_object(VERB_OB_CAST));
    
  spell_obname = find_spell_obname(spell);
  ENSURE(spell_obname);

  return spell_obname->_cast_spell(target, reagent);
}

void register_spell()
{
  string spell_name = previous_object()->get_spell_name();
  string spell_info = spell_table[spell_name];

  ENSURE(spell_name /* You didn't provide a spell name. */);
  ENSURE(valid_spell_name(spell_name) /* Your spell name wasn't valid. */);

  if ( !spell_info )
  {
    string obname = file_name(previous_object());
    string * file_info = split_path(obname);
    int dir_index = member_array(file_info[0], spell_dirs);

    if ( dir_index == -1 )
      error("spell is not in a legal directory\n");

    spell_table[spell_name] = obname;
  }

  ENSURE(find_object(get_spell_obname(spell_name)) == previous_object() 
/* Some other spell already has this name.*/);
}