deltamud/deltamud/
deltamud/deltamud/bin/
deltamud/deltamud/cnf/
deltamud/deltamud/lib/
deltamud/deltamud/lib/etc/
deltamud/deltamud/lib/misc/
deltamud/deltamud/lib/plrobjs/
deltamud/deltamud/lib/text/
deltamud/deltamud/lib/text/help/
deltamud/deltamud/lib/world/
deltamud/deltamud/lib/world/trg/
/* ************************************************************************
   *   File: spell_parser.c                                Part of CircleMUD *
   *  Usage: top-level magic routines; outside points of entry to magic sys. *
   *                                                                         *
   *  All rights reserved.  See license.doc for complete information.        *
   *                                                                         *
   *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
   *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
   ************************************************************************ */


#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "interpreter.h"
#include "spells.h"
#include "handler.h"
#include "comm.h"
#include "db.h"

struct spell_info_type spell_info[TOP_SPELL_DEFINE + 1];

#define SINFO spell_info[spellnum]

extern struct room_data *world;

/*
 * This arrangement is pretty stupid, but the number of skills is limited by
 * the playerfile.  We can arbitrarily increase the number of skills by
 * increasing the space in the playerfile. Meanwhile, this should provide
 * ample slots for skills.
 */

char *spells[] =
{
  "!RESERVED!",			/* 0 - reserved */

  /* SPELLS */

  "armor",			/* 1 */
  "teleport",
  "bless",
  "blindness",
  "charm person",
  "clone",
  "control weather",
  "create food",
  "create water",
  "cure blind",			/* 10 */
  "cure critic",
  "cure light",
  "curse",
  "detect alignment",
  "detect invisibility",
  "detect magic",
  "detect poison",
  "earthquake",
  "enchant weapon",
  "heal",			/* 20 */
  "invisibility",
  "locate object",
  "poison",
  "remove curse",
  "sanctuary",
  "sleep",
  "strength",
  "summon",
  "word of recall",
  "remove poison",		/* 30 */
  "sense life",
  "animate dead",
  "group armor",
  "group heal",
  "group recall",
  "infravision",
  "waterwalk",
  "stone skin",
  "fear",
  "recharge",			/* 40 */
  "portal",
  "group stone skin",
  "locate life",
  "convergence of power",
  "mana autus",
  "resist portal",
  "regen mana",
  "home",
  "word of retreat",
  "chain footing",			/* 50 */
  "redirect charge", 
  "!UNUSED", 
  "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 55 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 60 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 65 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 70 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 75 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 80 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 85 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 90 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 95 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 100 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 105 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 110 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 115 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 120 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 125 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 130 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 135 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 140 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 145 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 150 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 155 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 160 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 165 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 170 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 175 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 180 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 185 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 190 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 195 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 200 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 205 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 210 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 215 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 220 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 225 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 230 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 235 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 240 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 245 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 250 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 255 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 260 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 265 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 270 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 275 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 280 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 285 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 290 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 295 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 300 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 305 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 310 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 315 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 320 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 325 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 330 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 335 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 340 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 345 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 350 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 355 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 360 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 365 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 370 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 375 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 380 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 385 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 390 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 395 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 400 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 405 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 410 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 415 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 420 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 425 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 430 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 435 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 440 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 445 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 450 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 455 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 460 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 465 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 470 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 475 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 480 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 485 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 490 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 495 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 500 */

 /* SKILLS */
  "backstab",			/* 501 */
  "bash",
  "hide",
  "kick",
  "pick lock",
  "punch",
  "rescue",
  "sneak",
  "steal",
  "track",			/* 510 */
  "forage",
  "scan",
  "brew",
  "forge",
  "scribe",	/* 515 */
  "speed",
  "berserk",
  "camouflage",
  "blanket",
  "ram",	        /* 520 */
  "mount",
  "riding",
  "tame",
  "second attack",
  "third attack",	/* 525 */
  "listen",
  "meditate",
  "repair",
  "tan",
  "fillet",	/* 530 */
  "carve",
  "dodge",
  "parry",
  "avoid",
  "riposte",	/* 535 */
  "circle",
  "trip",
  "disarm",
  "target",
  "adrenaline",  /* 540 */
  "bloodlust",
  "carnal rage", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 545 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 550 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 555 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 560 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 565 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",	/* 570 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 575 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 580 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 585 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 590 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 595 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 600 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 605 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 610 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 615 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 620 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 625 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 630 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 635 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 640 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 645 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 650 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 655 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 660 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 665 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 670 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 675 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 680 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 685 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 690 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 695 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 700 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 705 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 710 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 715 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 720 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 725 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 730 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 735 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 740 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 745 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 750 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 755 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 760 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 765 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 770 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 775 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 780 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 785 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 790 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 795 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 800 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 805 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 810 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 815 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 820 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 825 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 830 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 835 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 840 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 845 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 850 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 855 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 860 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 865 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 870 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 875 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 880 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 885 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 890 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 895 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 900 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 905 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 910 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 915 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 920 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 925 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 930 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 935 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 940 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 945 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 950 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 955 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 960 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 965 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 970 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 975 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 980 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 985 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 990 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 995 */
  "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!", "!UNUSED!",   /* 1000 */

 
/* OBJECT SPELLS AND NPC SPELLS/SKILLS */

  "identify",			/* 1001(?) */
  "fire breath",
  "gas breath",
  "frost breath",
  "acid breath",
  "lightning breath",          /* 1005 */

  "\n"				/* the end */
};


struct syllable
  {
    char *org;
    char *new;
  };


struct syllable syls[] =
{
  {" ", " "},
  {"ar", "abra"},
  {"ate", "i"},
  {"cau", "kada"},
  {"blind", "nose"},
  {"bur", "mosa"},
  {"cu", "judi"},
  {"de", "oculo"},
  {"dis", "mar"},
  {"ect", "kamina"},
  {"en", "uns"},
  {"gro", "cra"},
  {"light", "dies"},
  {"lo", "hi"},
  {"magi", "kari"},
  {"mon", "bar"},
  {"mor", "zak"},
  {"move", "sido"},
  {"ness", "lacri"},
  {"ning", "illa"},
  {"per", "duda"},
  {"ra", "gru"},
  {"re", "candus"},
  {"son", "sabru"},
  {"tect", "infra"},
  {"tri", "cula"},
  {"ven", "nofo"},
  {"word of", "inset"},
  {"a", "i"},
  {"b", "v"},
  {"c", "q"},
  {"d", "m"},
  {"e", "o"},
  {"f", "y"},
  {"g", "t"},
  {"h", "p"},
  {"i", "u"},
  {"j", "y"},
  {"k", "t"},
  {"l", "r"},
  {"m", "w"},
  {"n", "b"},
  {"o", "a"},
  {"p", "s"},
  {"q", "d"},
  {"r", "f"},
  {"s", "g"},
  {"t", "h"},
  {"u", "e"},
  {"v", "z"},
  {"w", "x"},
  {"x", "n"},
  {"y", "l"},
  {"z", "k"},
  {"", ""}
};


int 
mag_manacost (struct char_data *ch, int spellnum)
{
  int mana;

  mana = MAX (SINFO.mana_max - (SINFO.mana_change *
		  (GET_LEVEL (ch) - SINFO.min_level[(int) GET_CLASS (ch)])),
	      SINFO.mana_min);

  /* If char is affected by mana autus, halve the mana */
  if (IS_AFFECTED(ch, AFF_AUTUS))
    mana >>= 1;

  return mana;
}


/* say_spell erodes buf, buf1, buf2 */
void 
say_spell (struct char_data *ch, int spellnum, struct char_data *tch,
	   struct obj_data *tobj)
{
  char lbuf[256];

  struct char_data *i;
  int j, ofs = 0;

  *buf = '\0';
  strcpy (lbuf, spells[spellnum]);

  while (*(lbuf + ofs))
    {
      for (j = 0; *(syls[j].org); j++)
	{
	  if (!strncmp (syls[j].org, lbuf + ofs, strlen (syls[j].org)))
	    {
	      strcat (buf, syls[j].new);
	      ofs += strlen (syls[j].org);
	    }
	}
    }

  if (tch != NULL && tch->in_room == ch->in_room)
    {
      if (tch == ch)
	sprintf (lbuf, "$n closes $s eyes and utters the words, '%%s'.");
      else
	sprintf (lbuf, "$n stares at $N and utters the words, '%%s'.");
    }
  else if (tobj != NULL &&
	   ((tobj->in_room == ch->in_room) || (tobj->carried_by == ch)))
    sprintf (lbuf, "$n stares at $p and utters the words, '%%s'.");
  else
    sprintf (lbuf, "$n utters the words, '%%s'.");

  sprintf (buf1, lbuf, spells[spellnum]);
  sprintf (buf2, lbuf, buf);

  for (i = world[ch->in_room].people; i; i = i->next_in_room)
    {
      if (i == ch || i == tch || !i->desc || !AWAKE (i))
	continue;
      if (GET_CLASS (ch) == GET_CLASS (i))
	perform_act (buf1, ch, tobj, tch, i);
      else
	perform_act (buf2, ch, tobj, tch, i);
    }

  /* Arena mods - Thargor */
  /* Why do we take the caster's and the recipient points of view? 
   * Not their view of the events, we use a bystander's desc of the 
   * events, but report to the caster's AND receipient's observers.
   * We cannot assume that there are other bystanders from which 
   * to look at things through.
   */
  /* From the caster's point of view */
  i = OBSERVE_BY(ch);
  while (i != NULL){
      if (GET_CLASS (ch) == GET_CLASS (i))
	perform_act (buf1, ch, tobj, tch, i);
      else
	perform_act (buf2, ch, tobj, tch, i);

       i = OBSERVE_BY(i);
  }

  if (tch != NULL && tch != ch && tch->in_room == ch->in_room)
    {
      /* Arena mods - Thargor */
      /* From the receipient's point of view */
      i = OBSERVE_BY(tch);
      while (i != NULL){
	if (GET_CLASS (tch) == GET_CLASS (i))
	  perform_act (buf1, ch, tobj, tch, i);
	else
	  perform_act (buf2, ch, tobj, tch, i);
	
	i = OBSERVE_BY(i);
      }

      sprintf (buf1, "$n stares at you and utters the words, '%s'.",
	       GET_CLASS (ch) == GET_CLASS (tch) ? spells[spellnum] : buf);
      act (buf1, FALSE, ch, NULL, tch, TO_VICT);
    }
}


char *
skill_name (int num)
{
  int i = 0;

  if (num <= 0)
    {
      if (num == -1)
	return "UNUSED";
      else
	return "UNDEFINED";
    }

  while (num && *spells[i] != '\n')
    {
      num--;
      i++;
    }

  if (*spells[i] != '\n')
    return spells[i];
  else
    return "UNDEFINED";
}


int 
find_skill_num (char *name)
{
  int index = 0, ok;
  char *temp, *temp2;
  char first[256], first2[256];

  while (*spells[++index] != '\n')
    {
      if (is_abbrev (name, spells[index]))
	return index;

      ok = 1;
      temp = any_one_arg (spells[index], first);
      temp2 = any_one_arg (name, first2);
      while (*first && *first2 && ok)
	{
	  if (!is_abbrev (first2, first))
	    ok = 0;
	  temp = any_one_arg (temp, first);
	  temp2 = any_one_arg (temp2, first2);
	}

      if (ok && !*first2)
	return index;
    }

  return -1;
}



/*
 * This function is the very heart of the entire magic system.  All
 * invocations of all types of magic -- objects, spoken and unspoken PC
 * and NPC spells, the works -- all come through this function eventually.
 * This is also the entry point for non-spoken or unrestricted spells.
 * Spellnum 0 is legal but silently ignored here, to make callers simpler.
 */
int 
call_magic (struct char_data *caster, struct char_data *cvict,
	    struct obj_data *ovict, int spellnum, int level)
{
  ASPELL(spell_locate_target);
  ASPELL(spell_home);
  ASPELL(spell_retreat);

  if (spellnum < 1 || spellnum > TOP_SPELL_DEFINE)
    return 0;

  if (ROOM_FLAGGED (caster->in_room, ROOM_NOMAGIC) && GET_LEVEL (caster) < LVL_IMPL)
    {
      send_to_char ("Your magic fizzles out and dies.\r\n", caster);
      act ("$n's magic fizzles out and dies.", FALSE, caster, 0, 0, TO_ROOM);
      return 0;
    }


  if (GET_LEVEL (caster) < LVL_IMPL && IS_SET (ROOM_FLAGS (caster->in_room), ROOM_PEACEFUL) &&
      (SINFO.violent || IS_SET (SINFO.routines, MAG_DAMAGE)))
    {
      send_to_char ("A flash of white light fills the room, dispelling your "
		    "violent magic!\r\n", caster);
      act ("White light from no particular source suddenly fills the room, "
	   "then vanishes.", FALSE, caster, 0, 0, TO_ROOM);
      return 0;
    }

  if (IS_SET (SINFO.routines, MAG_DAMAGE))
    mag_damage (level, caster, cvict, spellnum);

  if (IS_SET (SINFO.routines, MAG_AFFECTS))
    mag_affects (level, caster, cvict, spellnum);

  if (IS_SET (SINFO.routines, MAG_UNAFFECTS))
    mag_unaffects (level, caster, cvict, spellnum);

  if (IS_SET (SINFO.routines, MAG_POINTS))
    mag_points (level, caster, cvict, spellnum);

  if (IS_SET (SINFO.routines, MAG_ALTER_OBJS))
    mag_alter_objs (level, caster, ovict, spellnum);

  if (IS_SET (SINFO.routines, MAG_GROUPS))
    mag_groups (level, caster, spellnum);

  if (IS_SET (SINFO.routines, MAG_MASSES))
    mag_masses (level, caster, spellnum);

  if (IS_SET (SINFO.routines, MAG_AREAS))
    mag_areas (level, caster, spellnum);

  if (IS_SET (SINFO.routines, MAG_SUMMONS))
    mag_summons (level, caster, ovict, spellnum);

  if (IS_SET (SINFO.routines, MAG_CREATIONS))
    mag_creations (level, caster, spellnum);

  if (IS_SET (SINFO.routines, MAG_MANUAL))
    switch (spellnum)
      {
      case SPELL_CHARM:
	MANUAL_SPELL (spell_charm);
	break;
      case SPELL_CREATE_WATER:
	MANUAL_SPELL (spell_create_water);
	break;
      case SPELL_DETECT_POISON:
	MANUAL_SPELL (spell_detect_poison);
	break;
      case SPELL_ENCHANT_WEAPON:
	MANUAL_SPELL (spell_enchant_weapon);
	break;
      case SPELL_IDENTIFY:
	MANUAL_SPELL (spell_identify);
	break;
      case SPELL_LOCATE_OBJECT:
	MANUAL_SPELL (spell_locate_object);
	break;
      case SPELL_SUMMON:
	MANUAL_SPELL (spell_summon);
	break;
      case SPELL_WORD_OF_RECALL:
	MANUAL_SPELL (spell_recall);
	break;
      case SPELL_FEAR:
	MANUAL_SPELL (spell_fear);
	break;
      case SPELL_RECHARGE:
        MANUAL_SPELL (spell_recharge);
        break;
      case SPELL_PORTAL:
        MANUAL_SPELL(spell_portal);
        break;
      case SPELL_LOCATE_TARGET:
        MANUAL_SPELL(spell_locate_target);
        break;
      case SPELL_HOME:
        MANUAL_SPELL(spell_home);
        break;
      case SPELL_WORD_OF_RETREAT:
        MANUAL_SPELL(spell_retreat);
        break;
      }

  return 1;
}

/*
 * mag_objectmagic: This is the entry-point for all magic items.  This should
 * only be called by the 'quaff', 'use', 'recite', etc. routines.
 *
 * For reference, object values 0-3:
 * staff  - [0] level   [1] max charges [2] num charges [3] spell num
 * wand   - [0] level   [1] max charges [2] num charges [3] spell num
 * scroll - [0] level   [1] spell num   [2] spell num   [3] spell num
 * potion - [0] level   [1] spell num   [2] spell num   [3] spell num
 *
 * Staves and wands will default to level 14 if the level is not specified;
 * the DikuMUD format did not specify staff and wand levels in the world
 * files (this is a CircleMUD enhancement).
 */

void 
mag_objectmagic (struct char_data *ch, struct obj_data *obj,
		 char *argument)
{
  int i, k;
  struct char_data *tch = NULL, *next_tch;
  struct obj_data *tobj = NULL;

  one_argument (argument, arg);

  k = generic_find (arg, FIND_CHAR_ROOM | FIND_OBJ_INV | FIND_OBJ_ROOM |
		    FIND_OBJ_EQUIP, ch, &tch, &tobj);

  if (!IS_NPC(ch) && tch != NULL){
    if (!IS_NPC(tch))
      if (GET_LEVEL (ch) < LVL_IMMORT && GET_LEVEL(tch) >= LVL_IMMORT){
	send_to_char ("A blinding flash of white light dispels your magic!\r\n", ch);
	act ("$n attempts to cast magic on $N.\r\n"
	     "A blinding flash of white light dispels $n's magic.", 
	     FALSE, ch, 0, tch, TO_ROOM);
	return; 
      }
  }

  switch (GET_OBJ_TYPE (obj))
    {
    case ITEM_STAFF:
      act ("You tap $p three times on the ground.", FALSE, ch, obj, 0, TO_CHAR);
      if (obj->action_description)
	act (obj->action_description, FALSE, ch, obj, 0, TO_ROOM);
      else
	act ("$n taps $p three times on the ground.", FALSE, ch, obj, 0, TO_ROOM);

      if (GET_OBJ_VAL (obj, 2) <= 0)
	{
	  act ("It seems powerless.", FALSE, ch, obj, 0, TO_CHAR);
	  act ("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM);
	}
      else
	{
	  GET_OBJ_VAL (obj, 2)--;
	  WAIT_STATE (ch, PULSE_VIOLENCE);
	  for (tch = world[ch->in_room].people; tch; tch = next_tch)
	    {
	      next_tch = tch->next_in_room;
	      if (ch == tch)
		continue;
	      if (GET_OBJ_VAL (obj, 0))
		call_magic (ch, tch, NULL, GET_OBJ_VAL (obj, 3),
			    GET_OBJ_VAL (obj, 0));
	      else
		call_magic (ch, tch, NULL, GET_OBJ_VAL (obj, 3),
			    DEFAULT_STAFF_LVL);
	    }
	}
      break;
    case ITEM_WAND:
      if (k == FIND_CHAR_ROOM)
	{
	  if (tch == ch)
	    {
	      act ("You point $p at yourself.", FALSE, ch, obj, 0, TO_CHAR);
	      act ("$n points $p at $mself.", FALSE, ch, obj, 0, TO_ROOM);
	    }
	  else
	    {
	      act ("You point $p at $N.", FALSE, ch, obj, tch, TO_CHAR);
	      if (obj->action_description != NULL)
		act (obj->action_description, FALSE, ch, obj, tch, TO_ROOM);
	      else
		act ("$n points $p at $N.", TRUE, ch, obj, tch, TO_ROOM);
	    }
	}
      else if (tobj != NULL)
	{
	  act ("You point $p at $P.", FALSE, ch, obj, tobj, TO_CHAR);
	  if (obj->action_description != NULL)
	    act (obj->action_description, FALSE, ch, obj, tobj, TO_ROOM);
	  else
	    act ("$n points $p at $P.", TRUE, ch, obj, tobj, TO_ROOM);
	}
      else
	{
	  act ("At what should $p be pointed?", FALSE, ch, obj, NULL, TO_CHAR);
	  return;
	}

      if (GET_OBJ_VAL (obj, 2) <= 0)
	{
	  act ("It seems powerless.", FALSE, ch, obj, 0, TO_CHAR);
	  act ("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM);
	  return;
	}
      GET_OBJ_VAL (obj, 2)--;
      WAIT_STATE (ch, PULSE_VIOLENCE);
      if (GET_OBJ_VAL (obj, 0))
	call_magic (ch, tch, tobj, GET_OBJ_VAL (obj, 3),
		    GET_OBJ_VAL (obj, 0));
      else
	call_magic (ch, tch, tobj, GET_OBJ_VAL (obj, 3),
		    DEFAULT_WAND_LVL);
      break;
    case ITEM_SCROLL:
      if (*arg)
	{
	  if (!k)
	    {
	      act ("There is nothing to here to affect with $p.", FALSE,
		   ch, obj, NULL, TO_CHAR);
	      return;
	    }
	}
      else
	tch = ch;

      act ("You recite $p which dissolves.", TRUE, ch, obj, 0, TO_CHAR);
      if (obj->action_description)
	act (obj->action_description, FALSE, ch, obj, NULL, TO_ROOM);
      else
	act ("$n recites $p.", FALSE, ch, obj, NULL, TO_ROOM);

      WAIT_STATE (ch, PULSE_VIOLENCE);
      for (i = 1; i < 4; i++)
	if (!(call_magic (ch, tch, tobj, GET_OBJ_VAL (obj, i),
			  GET_OBJ_VAL (obj, 0))))
	  break;

      if (obj != NULL)
	extract_obj (obj);
      break;
    case ITEM_POTION:
      tch = ch;
      act ("You quaff $p.", FALSE, ch, obj, NULL, TO_CHAR);
      if (obj->action_description)
	act (obj->action_description, FALSE, ch, obj, NULL, TO_ROOM);
      else
	act ("$n quaffs $p.", TRUE, ch, obj, NULL, TO_ROOM);

      WAIT_STATE (ch, PULSE_VIOLENCE);
      for (i = 1; i < 4; i++)
	if (!(call_magic (ch, ch, NULL, GET_OBJ_VAL (obj, i),
			  GET_OBJ_VAL (obj, 0))))
	  break;

      if (obj != NULL)
	extract_obj (obj);
      break;
    default:
      log ("SYSERR: Unknown object_type in mag_objectmagic");
      break;
    }
}


/*
 * cast_spell is used generically to cast any spoken spell, assuming we
 * already have the target char/obj and spell number.  It checks all
 * restrictions, etc., prints the words, etc.
 *
 * Entry point for NPC casts.  Recommended entry point for spells cast
 * by NPCs via specprocs.
 */

int 
cast_spell (struct char_data *ch, struct char_data *tch,
	    struct obj_data *tobj, int spellnum)
{
  char buf[256];

  if (spellnum < 0 || spellnum > TOP_SPELL_DEFINE)
    {
      sprintf (buf, "SYSERR: cast_spell trying to call spellnum %d\n", spellnum);
      log (buf);
      return 0;
    }

  if (GET_POS (ch) < SINFO.min_position)
    {
      switch (GET_POS (ch))
	{
	case POS_SLEEPING:
	  send_to_char ("You dream about great magical powers.\r\n", ch);
	  break;
	case POS_RESTING:
	  send_to_char ("You cannot concentrate while resting.\r\n", ch);
	  break;
	case POS_SITTING:
	  send_to_char ("You can't do this sitting!\r\n", ch);
	  break;
	case POS_FIGHTING:
	  send_to_char ("Impossible!  You can't concentrate enough!\r\n", ch);
	  break;
	default:
	  send_to_char ("You can't do much of anything like this!\r\n", ch);
	  break;
	}
      return 0;
    }
  if (IS_AFFECTED (ch, AFF_CHARM) && (ch->master == tch))
    {
      send_to_char ("You are afraid you might hurt your master!\r\n", ch);
      return 0;
    }
  if ((tch != ch) && IS_SET (SINFO.targets, TAR_SELF_ONLY))
    {
      send_to_char ("You can only cast this spell upon yourself!\r\n", ch);
      return 0;
    }
  if ((tch == ch) && IS_SET (SINFO.targets, TAR_NOT_SELF))
    {
      send_to_char ("You cannot cast this spell upon yourself!\r\n", ch);
      return 0;
    }
  if (IS_SET (SINFO.routines, MAG_GROUPS) && !IS_AFFECTED (ch, AFF_GROUP))
    {
      send_to_char ("You can't cast this spell if you're not in a group!\r\n", ch);
      return 0;
    }
  send_to_char (OK, ch);
  say_spell (ch, spellnum, tch, tobj);

  return (call_magic (ch, tch, tobj, spellnum, GET_LEVEL (ch)));
}


/*
 * do_cast is the entry point for PC-casted spells.  It parses the arguments,
 * determines the spell number and finds a target, throws the die to see if
 * the spell can be cast, checks for sufficient mana and subtracts it, and
 * passes control to cast_spell().
 */

ACMD (do_cast)
{
  struct char_data *tch = NULL;
  struct obj_data *tobj = NULL;
  char *s, *t;
  int mana, spellnum, i, target = 0;

  if (IS_NPC (ch))
    return;

  /* get: blank, spell name, target name */
  s = strtok (argument, "'");

  if (s == NULL)
    {
      send_to_char ("Cast what where?\r\n", ch);
      return;
    }
  s = strtok (NULL, "'");
  if (s == NULL)
    {
      send_to_char ("Spell names must be enclosed in the Holy Magic Symbols: '\r\n", ch);
      return;
    }
  t = strtok (NULL, "\0");

  /* spellnum = search_block(s, spells, 0); */
  spellnum = find_skill_num (s);

  if ((spellnum < 1) || (spellnum > MAX_SPELLS))
    {
      send_to_char ("Cast what?!?\r\n", ch);
      return;
    }
  if (GET_LEVEL (ch) < SINFO.min_level[(int) GET_CLASS (ch)])
    {
      send_to_char ("You do not know that spell!\r\n", ch);
      return;
    }
  if (GET_SKILL (ch, spellnum) == 0)
    {
      send_to_char ("You are unfamiliar with that spell.\r\n", ch);
      return;
    }
  /* Find the target */
  if (t != NULL)
    {
      one_argument (strcpy (arg, t), t);
      skip_spaces (&t);
    }
  if (IS_SET (SINFO.targets, TAR_IGNORE))
    {
      target = TRUE;
    }
  else if (t != NULL && *t)
    {
      if (!target && (IS_SET (SINFO.targets, TAR_CHAR_ROOM)))
	{
	  if ((tch = get_char_room_vis (ch, t)) != NULL)
	    target = TRUE;
	}
      if (!target && IS_SET (SINFO.targets, TAR_CHAR_WORLD))
	if ((tch = get_char_vis (ch, t)))
	  target = TRUE;

      if (!target && IS_SET (SINFO.targets, TAR_OBJ_INV))
	if ((tobj = get_obj_in_list_vis (ch, t, ch->carrying)))
	  target = TRUE;

      if (!target && IS_SET (SINFO.targets, TAR_OBJ_EQUIP))
	{
	  for (i = 0; !target && i < NUM_WEARS; i++)
	    if (GET_EQ (ch, i) && CAN_SEE_OBJ (ch, GET_EQ (ch, i)) &&
		isname (t, GET_EQ (ch, i)->name))
	      {
		tobj = GET_EQ (ch, i);
		target = TRUE;
	      }
	}
      if (!target && IS_SET (SINFO.targets, TAR_OBJ_ROOM))
	if ((tobj = get_obj_in_list_vis (ch, t, world[ch->in_room].contents)))
	  target = TRUE;

      if (!target && IS_SET (SINFO.targets, TAR_OBJ_WORLD))
	if ((tobj = get_obj_vis (ch, t)))
	  target = TRUE;

    }
  else
    {				/* if target string is empty */
      if (!target && IS_SET (SINFO.targets, TAR_FIGHT_SELF))
	if (FIGHTING (ch) != NULL)
	  {
	    tch = ch;
	    target = TRUE;
	  }
      if (!target && IS_SET (SINFO.targets, TAR_FIGHT_VICT))
	if (FIGHTING (ch) != NULL)
	  {
	    tch = FIGHTING (ch);
	    target = TRUE;
	  }
      /* if no target specified, and the spell isn't violent, default to self */
      if (!target && IS_SET (SINFO.targets, TAR_CHAR_ROOM) &&
	  !SINFO.violent)
	{
	  tch = ch;
	  target = TRUE;
	}
      if (!target)
	{
	  sprintf (buf, "Upon %s should the spell be cast?\r\n",
		   IS_SET (SINFO.targets, TAR_OBJ_ROOM | TAR_OBJ_INV | TAR_OBJ_WORLD) ?
		   "what" : "who");
	  send_to_char (buf, ch);
	  return;
	}
    }

  if (target && (tch == ch) && SINFO.violent)
    {
      send_to_char ("You shouldn't cast that on yourself -- could be bad for your health!\r\n", ch);
      return;
    }
  if (!target)
    {
      send_to_char ("Cannot find the target of your spell!\r\n", ch);
      return;
    }
  mana = mag_manacost (ch, spellnum);
  if ((mana > 0) && (GET_MANA (ch) < mana) && (GET_LEVEL (ch) < LVL_IMMORT))
    {
      send_to_char ("You haven't the energy to cast that spell!\r\n", ch);
      return;
    }

  /* You throws the dice and you takes your chances.. 101% is total failure */
  if (number (0, 101) > GET_SKILL (ch, spellnum))
    {
      WAIT_STATE (ch, PULSE_VIOLENCE);
      if (!tch || !skill_message (0, ch, tch, spellnum))
	send_to_char ("You lost your concentration!\r\n", ch);
      if (mana > 0)
	GET_MANA (ch) = MAX (0, MIN (GET_MAX_MANA (ch), GET_MANA (ch) - (mana >> 1)));
      if (SINFO.violent && tch && IS_NPC (tch))
	hit (tch, ch, TYPE_UNDEFINED);
    }
  else
    {				/* cast spell returns 1 on success; subtract mana & set waitstate */
      if (cast_spell (ch, tch, tobj, spellnum))
	{
	  WAIT_STATE (ch, PULSE_VIOLENCE);
	  if (mana > 0)
	    GET_MANA (ch) = MAX (0, MIN (GET_MAX_MANA (ch), GET_MANA (ch) - mana));
	}
    }
}



void 
spell_level (int spell, int class, int level)
{
  char buf[256];
  int bad = 0;

  if (spell < 0 || spell > TOP_SPELL_DEFINE)
    {
      sprintf (buf, "SYSERR: attempting assign to illegal spellnum %d", spell);
      log (buf);
      return;
    }

  if (class < 0 || class >= NUM_CLASSES)
    {
      sprintf (buf, "SYSERR: assigning '%s' to illegal class %d",
	       skill_name (spell), class);
      log (buf);
      bad = 1;
    }

  if (level < 1 || level > LVL_IMPL)
    {
      sprintf (buf, "SYSERR: assigning '%s' to illegal level %d",
	       skill_name (spell), level);
      log (buf);
      bad = 1;
    }

  if (!bad)
    spell_info[spell].min_level[class] = level;
}


/* Assign the spells on boot up */
void 
spello (int spl, int max_mana, int min_mana, int mana_change, int minpos,
	int targets, int violent, int routines)
{
  int i;

  for (i = 0; i < NUM_CLASSES; i++)
    spell_info[spl].min_level[i] = LVL_IMMORT;
  spell_info[spl].mana_max = max_mana;
  spell_info[spl].mana_min = min_mana;
  spell_info[spl].mana_change = mana_change;
  spell_info[spl].min_position = minpos;
  spell_info[spl].targets = targets;
  spell_info[spl].violent = violent;
  spell_info[spl].routines = routines;
}


void 
unused_spell (int spl)
{
  int i;

  for (i = 0; i < NUM_CLASSES; i++)
    spell_info[spl].min_level[i] = LVL_IMPL + 1;
  spell_info[spl].mana_max = 0;
  spell_info[spl].mana_min = 0;
  spell_info[spl].mana_change = 0;
  spell_info[spl].min_position = 0;
  spell_info[spl].targets = 0;
  spell_info[spl].violent = 0;
  spell_info[spl].routines = 0;
}

#define skillo(skill) spello(skill, 0, 0, 0, 0, 0, 0, 0);


/*
 * Arguments for spello calls:
 *
 * spellnum, maxmana, minmana, manachng, minpos, targets, violent?, routines.
 *
 * spellnum:  Number of the spell.  Usually the symbolic name as defined in
 * spells.h (such as SPELL_HEAL).
 *
 * maxmana :  The maximum mana this spell will take (i.e., the mana it
 * will take when the player first gets the spell).
 *
 * minmana :  The minimum mana this spell will take, no matter how high
 * level the caster is.
 *
 * manachng:  The change in mana for the spell from level to level.  This
 * number should be positive, but represents the reduction in mana cost as
 * the caster's level increases.
 *
 * minpos  :  Minimum position the caster must be in for the spell to work
 * (usually fighting or standing). targets :  A "list" of the valid targets
 * for the spell, joined with bitwise OR ('|').
 *
 * violent :  TRUE or FALSE, depending on if this is considered a violent
 * spell and should not be cast in PEACEFUL rooms or on yourself.  Should be
 * set on any spell that inflicts damage, is considered aggressive (i.e.
 * charm, curse), or is otherwise nasty.
 *
 * routines:  A list of magic routines which are associated with this spell
 * if the spell uses spell templates.  Also joined with bitwise OR ('|').
 *
 * See the CircleMUD documentation for a more detailed description of these
 * fields.
 */

/*
 * NOTE: SPELL LEVELS ARE NO LONGER ASSIGNED HERE AS OF Circle 3.0 bpl9.
 * In order to make this cleaner, as well as to make adding new classes
 * much easier, spell levels are now assigned in class.c.  You only need
 * a spello() call to define a new spell; to decide who gets to use a spell
 * or skill, look in class.c.  -JE 5 Feb 1996
 */

void 
mag_assign_spells (void)
{
  int i;

  /* Do not change the loop below */
  for (i = 1; i <= TOP_SPELL_DEFINE; i++)
    unused_spell (i);
  /* Do not change the loop above */

  spello (SPELL_ANIMATE_DEAD, 175, 150, 3, POS_STANDING,
	  TAR_OBJ_ROOM, FALSE, MAG_SUMMONS);

  spello (SPELL_ARMOR, 30, 15, 3, POS_FIGHTING,
	  TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);

  spello (SPELL_BLESS, 35, 5, 3, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_OBJ_INV, FALSE, MAG_AFFECTS | MAG_ALTER_OBJS);

  spello (SPELL_BLINDNESS, 35, 25, 1, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_NOT_SELF, FALSE, MAG_AFFECTS);

  spello (SPELL_CHARM, 75, 50, 2, POS_FIGHTING,
	  TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_MANUAL);

  spello (SPELL_CLONE, 200, 150, 5, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_SUMMONS);

  spello (SPELL_CONTROL_WEATHER, 75, 25, 5, POS_STANDING,
	  TAR_IGNORE, FALSE, MAG_MANUAL);

  spello (SPELL_CREATE_FOOD, 30, 5, 4, POS_STANDING,
	  TAR_IGNORE, FALSE, MAG_CREATIONS);

  spello (SPELL_CREATE_WATER, 30, 5, 4, POS_STANDING,
	  TAR_OBJ_INV | TAR_OBJ_EQUIP, FALSE, MAG_MANUAL);

  spello (SPELL_CURE_BLIND, 30, 5, 2, POS_STANDING,
	  TAR_CHAR_ROOM, FALSE, MAG_UNAFFECTS);

  spello (SPELL_CURE_CRITIC, 30, 10, 2, POS_FIGHTING,
	  TAR_CHAR_ROOM, FALSE, MAG_POINTS);

  spello (SPELL_CURE_LIGHT, 30, 10, 2, POS_FIGHTING,
	  TAR_CHAR_ROOM, FALSE, MAG_POINTS);

  spello (SPELL_CURSE, 80, 50, 2, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_OBJ_INV, TRUE, MAG_AFFECTS | MAG_ALTER_OBJS);

  spello (SPELL_DETECT_ALIGN, 20, 10, 2, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

  spello (SPELL_DETECT_INVIS, 20, 10, 2, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

  spello (SPELL_DETECT_MAGIC, 20, 10, 2, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

  spello (SPELL_DETECT_POISON, 15, 5, 1, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL);

  spello (SPELL_EARTHQUAKE, 40, 25, 3, POS_FIGHTING,
	  TAR_IGNORE, TRUE, MAG_AREAS);

  spello (SPELL_ENCHANT_WEAPON, 150, 100, 10, POS_STANDING,
	  TAR_OBJ_INV | TAR_OBJ_EQUIP, FALSE, MAG_MANUAL);

  spello (SPELL_GROUP_ARMOR, 50, 30, 2, POS_STANDING,
	  TAR_IGNORE, FALSE, MAG_GROUPS);

  spello (SPELL_GROUP_HEAL, 80, 60, 5, POS_STANDING,
	  TAR_IGNORE, FALSE, MAG_GROUPS);

  spello (SPELL_HEAL, 60, 40, 3, POS_FIGHTING,
	  TAR_CHAR_ROOM, FALSE, MAG_POINTS | MAG_AFFECTS | MAG_UNAFFECTS);

  spello (SPELL_INFRAVISION, 25, 10, 1, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

  spello (SPELL_INVISIBLE, 35, 25, 1, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_AFFECTS | MAG_ALTER_OBJS);

  spello (SPELL_LOCATE_OBJECT, 25, 20, 1, POS_STANDING,
	  TAR_OBJ_WORLD, FALSE, MAG_MANUAL);

  spello (SPELL_LOCATE_TARGET, 100, 20, 1, POS_STANDING,
	 TAR_CHAR_WORLD, FALSE, MAG_MANUAL);

  spello (SPELL_POISON, 50, 20, 3, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_NOT_SELF | TAR_OBJ_INV, TRUE, MAG_AFFECTS | MAG_ALTER_OBJS);

  spello (SPELL_REMOVE_CURSE, 45, 25, 5, POS_STANDING,
	TAR_CHAR_ROOM | TAR_OBJ_INV, FALSE, MAG_UNAFFECTS | MAG_ALTER_OBJS);

  spello (SPELL_SANCTUARY, 110, 85, 5, POS_STANDING,
	  TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);

  spello (SPELL_SLEEP, 40, 25, 5, POS_STANDING,
	  TAR_CHAR_ROOM, TRUE, MAG_AFFECTS);

  spello (SPELL_STRENGTH, 35, 30, 1, POS_STANDING,
	  TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);

  spello (SPELL_SUMMON, 75, 50, 3, POS_STANDING,
	  TAR_CHAR_WORLD | TAR_NOT_SELF, FALSE, MAG_MANUAL);

  spello (SPELL_WORD_OF_RECALL, 20, 10, 2, POS_FIGHTING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_MANUAL);

  spello (SPELL_REMOVE_POISON, 40, 8, 4, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_UNAFFECTS | MAG_ALTER_OBJS);

  spello (SPELL_SENSE_LIFE, 20, 10, 2, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

  spello (SPELL_STONE_SKIN, 120, 60, 3, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

  spello (SPELL_FEAR, 100, 50, 1, POS_FIGHTING,
	  TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_MANUAL);

  spello (SPELL_RECHARGE, 150, 75, 1, POS_STANDING,
	  TAR_CHAR_ROOM | TAR_NOT_SELF | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL);

  spello(SPELL_PORTAL, 170, 100, 5, POS_STANDING,
       TAR_CHAR_WORLD | TAR_NOT_SELF, FALSE, MAG_MANUAL);

  spello (SPELL_GROUP_STONE_SKIN, 240, 120, 2, POS_STANDING,
          TAR_IGNORE, FALSE, MAG_GROUPS);

   spello (SPELL_CONVERGENCE, 110, 85, 5, POS_STANDING,
	  TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);

   spello (SPELL_AUTUS, 140, 100, 5, POS_STANDING,
	  TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);

   spello (SPELL_RESIST_PORTAL, 200, 100, 2, POS_STANDING,
          TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

   spello (SPELL_REGEN_MANA, 150, 150, 0, POS_FIGHTING,
	  TAR_CHAR_ROOM | TAR_NOT_SELF, FALSE, MAG_POINTS);

   spello (SPELL_HOME, 80, 20, 1, POS_FIGHTING,
          TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_MANUAL);

   spello (SPELL_WORD_OF_RETREAT, 30, 20, 1, POS_FIGHTING,
          TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_MANUAL);
 
  spello (SPELL_WATERWALK, 200, 150, 1, POS_FIGHTING,
          TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS);

  spello(SPELL_REDIRECT_CHARGE, 200, 100, 5, POS_STANDING,
	  TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);

  /* NON-castable spells should appear here */
  spello (SPELL_IDENTIFY, 0, 0, 0, 0,
	  TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL);


  /*
   * Declaration of skills - this actually doesn't do anything except
   * set it up so that immortals can use these skills by default.  The
   * min level to use the skill for other classes is set up in class.c.
   */

  skillo (SKILL_BACKSTAB);
  skillo (SKILL_BASH);
  skillo (SKILL_HIDE);
  skillo (SKILL_KICK);
  skillo (SKILL_BERSERK);
  skillo (SKILL_PICK_LOCK);
  skillo (SKILL_RAM_DOOR);
  skillo (SKILL_PUNCH);
  skillo (SKILL_RESCUE);
  skillo (SKILL_SNEAK);
  skillo (SKILL_CAMOUFLAGE);
  skillo (SKILL_BLANKET);
  skillo (SKILL_STEAL);
  skillo (SKILL_TRACK);
  skillo (SKILL_FORAGE);
  skillo (SKILL_SCAN);
  skillo (SKILL_BREW);
  skillo (SKILL_FORGE);
  skillo (SKILL_SCRIBE);
  skillo (SKILL_SPEED);
  skillo (SKILL_MOUNT);
  skillo (SKILL_RIDING);
  skillo (SKILL_TAME);
  skillo (SKILL_SECOND_ATTACK);
  skillo (SKILL_THIRD_ATTACK);
  skillo (SKILL_LISTEN);
  skillo (SKILL_MEDITATE);
  skillo (SKILL_REPAIR);
  skillo (SKILL_TAN);
  skillo (SKILL_FILLET);
  skillo (SKILL_CARVE);
  skillo (SKILL_DODGE);
  skillo (SKILL_PARRY);
  skillo (SKILL_AVOID);
  skillo (SKILL_RIPOSTE);
  skillo (SKILL_CIRCLE);
  skillo (SKILL_TRIP);
  skillo (SKILL_TARGET);
  skillo (SKILL_DISARM);
  skillo (SKILL_CHAIN_FOOTING);
  skillo (SKILL_ADRENALINE);
  skillo (SKILL_BLOODLUST);
  skillo (SKILL_CARNALRAGE);
}