wileymud-1.187b/
wileymud-1.187b/attic/
wileymud-1.187b/attic/bin/
wileymud-1.187b/attic/lib/
wileymud-1.187b/attic/lib/adm/
wileymud-1.187b/attic/lib/man/
wileymud-1.187b/attic/lib/new-wld/
wileymud-1.187b/attic/lib/new-wld/default/
wileymud-1.187b/attic/lib/old/
wileymud-1.187b/attic/lib/wld/
wileymud-1.187b/attic/public_html/
wileymud-1.187b/attic/public_html/gfx/
wileymud-1.187b/attic/src/bin/
wileymud-1.187b/attic/src/etc/
wileymud-1.187b/attic/src/libauth-4.0-p5/
wileymud-1.187b/attic/src/sedna/
wileymud-1.187b/backups/
wileymud-1.187b/bin/
wileymud-1.187b/docs/
wileymud-1.187b/etc/
wileymud-1.187b/lib/
wileymud-1.187b/lib/adm/
wileymud-1.187b/lib/boards/
wileymud-1.187b/lib/log/
wileymud-1.187b/lib/man/
wileymud-1.187b/lib/ply/
wileymud-1.187b/lib/ply/a/
wileymud-1.187b/lib/ply/b/
wileymud-1.187b/lib/ply/c/
wileymud-1.187b/lib/ply/d/
wileymud-1.187b/lib/ply/g/
wileymud-1.187b/lib/ply/k/
wileymud-1.187b/lib/ply/m/
wileymud-1.187b/lib/ply/s/
wileymud-1.187b/lib/ply/t/
wileymud-1.187b/public_html/gfx/
wileymud-1.187b/src/bin/
wileymud-1.187b/src/convert/attic/
wileymud-1.187b/src/convert/obj/
wileymud-1.187b/src/convert/perl/
wileymud-1.187b/src/convert/perl/MudConvert/
wileymud-1.187b/src/convert/perl/MudConvert/DUMP/
wileymud-1.187b/src/convert/perl/MudConvert/Report/
wileymud-1.187b/src/convert/perl/MudConvert/WileyMUD/
wileymud-1.187b/src/convert/perl/output/
wileymud-1.187b/src/convert/perl/output/DUMP/
wileymud-1.187b/src/convert/perl/output/Report/
wileymud-1.187b/src/convert/perl/output/WileyMUD/
wileymud-1.187b/src/etc/
wileymud-1.187b/src/etc/init.d/
wileymud-1.187b/src/etc/rc.d/
wileymud-1.187b/src/etc/rc.d/init.d/
wileymud-1.187b/src/lib/
wileymud-1.187b/src/lib/adm/
wileymud-1.187b/src/lib/boards/
wileymud-1.187b/src/lib/log/
wileymud-1.187b/src/lib/man/
wileymud-1.187b/src/lib/ply/
wileymud-1.187b/src/lib/ply/a/
wileymud-1.187b/src/lib/ply/b/
wileymud-1.187b/src/lib/ply/c/
wileymud-1.187b/src/lib/ply/d/
wileymud-1.187b/src/lib/ply/e/
wileymud-1.187b/src/lib/ply/f/
wileymud-1.187b/src/lib/ply/g/
wileymud-1.187b/src/lib/ply/h/
wileymud-1.187b/src/lib/ply/i/
wileymud-1.187b/src/lib/ply/j/
wileymud-1.187b/src/lib/ply/k/
wileymud-1.187b/src/lib/ply/l/
wileymud-1.187b/src/lib/ply/m/
wileymud-1.187b/src/lib/ply/n/
wileymud-1.187b/src/lib/ply/o/
wileymud-1.187b/src/lib/ply/p/
wileymud-1.187b/src/lib/ply/q/
wileymud-1.187b/src/lib/ply/r/
wileymud-1.187b/src/lib/ply/s/
wileymud-1.187b/src/lib/ply/t/
wileymud-1.187b/src/lib/ply/u/
wileymud-1.187b/src/lib/ply/v/
wileymud-1.187b/src/lib/ply/w/
wileymud-1.187b/src/lib/ply/x/
wileymud-1.187b/src/lib/ply/y/
wileymud-1.187b/src/lib/ply/z/
wileymud-1.187b/src/obj/
wileymud-1.187b/src/utils/
wileymud-1.187b/src/utils/mobmaker/
/*
 * file: magic.c , Implementation of spells.              Part of DIKUMUD
 * Usage : The actual effect of magic.
 * Copyright (C) 1990, 1991 - see 'license.doc' for complete information.
 */

#include <stdio.h>
#include <stdlib.h>
/* #include <unistd.h> */
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <assert.h>

#include "global.h"
#include "bug.h"
#include "utils.h"
#include "comm.h"
#include "handler.h"
#include "mudlimits.h"
#include "db.h"
#include "constants.h"
#include "spells.h"
#include "spell_parser.h"
#include "multiclass.h"
#include "fight.h"
#include "opinion.h"
#include "reception.h"
#include "magic_utils.h"
#include "act_off.h"
#include "act_obj.h"
#include "act_info.h"

void spell_armor(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || level < 0 || level > ABS_MAX_LVL)
	return;

    if (!affected_by_spell(victim, SPELL_ARMOR)) {
	af.type = SPELL_ARMOR;
	af.duration = GET_LEVEL(ch, BestMagicClass(ch));
	af.modifier = -20;
	af.location = APPLY_AC;
	af.bitvector = 0;

	affect_to_char(victim, &af);
	cprintf(victim, "You feel a strong protective force shimmer all around you.\r\n");
    } else {
	cprintf(ch, "You feel confident that you are still protected.\r\n");
    }
}

void spell_teleport(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    int                                     to_room = 0;
    struct room_data                       *room = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (IS_SET(victim->specials.new_act, NEW_PLR_TELEPORT)) {
	cprintf(ch, "You try to send it away, but it just smirks at you.\r\n");
	return;
    }
    if (victim != ch) {
	if (saves_spell(victim, SAVING_SPELL)) {
	    cprintf(ch, "Your target remains firmly in front of you.\r\n");
	    if (IS_NPC(victim)) {
		if (!victim->specials.fighting)
		    set_fighting(victim, ch);
	    } else {
		cprintf(victim, "You feel like you were somewhere else for just a moment.\r\n");
	    }
	    return;
	} else {
	    ch = victim;				       /* the character (target) is now the victim */
	}
    }
    do {
	to_room = number(0, top_of_world);
	room = real_roomp(to_room);
	if (room) {
	    if (IS_SET(room->room_flags, PRIVATE)
		|| IS_SET(room->room_flags, NO_SUM))
		room = 0;
	}
    } while (!room);

    if (MOUNTED(ch)) {
	char_from_room(ch);
	char_from_room(MOUNTED(ch));
	char_to_room(ch, to_room);
	char_to_room(MOUNTED(ch), to_room);
	act("$n and a mount slowly fade out of existence.", FALSE, ch, 0, 0, TO_ROOM);
	act("$n slowly fades into existence.", FALSE, ch, 0, 0, TO_ROOM);
    } else if (RIDDEN(ch)) {
	char_from_room(RIDDEN(ch));
	char_from_room(ch);
	char_to_room(RIDDEN(ch), to_room);
	char_to_room(ch, to_room);
	act("$n and a rider slowly fade out of existence.", FALSE, ch, 0, 0, TO_ROOM);
	act("$n slowly fades into existence.", FALSE, ch, 0, 0, TO_ROOM);
    } else {
	char_from_room(ch);
	char_to_room(ch, to_room);
	act("$n slowly fades out of existence.", FALSE, ch, 0, 0, TO_ROOM);
	act("$n slowly fades in to existence.", FALSE, ch, 0, 0, TO_ROOM);
    }

    /*
     * do_look(ch, "", 0); 
     */

    if (IS_SET(real_roomp(to_room)->room_flags, DEATH) && GetMaxLevel(ch) < LOW_IMMORTAL) {
	death_cry(ch);
	zero_rent(ch);
	extract_char(ch);
    }
}

void spell_bless(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || (!victim && !obj) || level < 0 || level > ABS_MAX_LVL)
	return;
    if (obj) {
	if ((10 * GET_LEVEL(ch, CLERIC_LEVEL_IND) > GET_OBJ_WEIGHT(obj)) &&
	    (GET_POS(ch) != POSITION_FIGHTING) && !IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)) {
	    SET_BIT(obj->obj_flags.extra_flags, ITEM_BLESS);
	    act("$p shimmers with light for a second.", FALSE, ch, obj, 0, TO_CHAR);
	}
    } else {
	if ((GET_POS(victim) != POSITION_FIGHTING) && (!affected_by_spell(victim, SPELL_BLESS))) {
	    cprintf(victim, "You feel righteous.\r\n");
	    af.type = SPELL_BLESS;
	    af.duration = level / 2;
	    af.modifier = 1;
	    af.location = APPLY_HITROLL;
	    af.bitvector = 0;
	    affect_to_char(victim, &af);
	    af.location = APPLY_SAVING_SPELL;
	    af.modifier = -1;				       /* Make better */
	    affect_to_char(victim, &af);
	}
    }
}

void spell_blindness(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (!CheckKill(ch, victim))
	return;

    if (saves_spell(victim, SAVING_SPELL) || affected_by_spell(victim, SPELL_BLINDNESS)) {
	if ((!victim->specials.fighting) && (victim != ch))
	    set_fighting(victim, ch);
	return;
    }
    act("$n clutches $s eyes and fumbles about!", TRUE, victim, 0, 0, TO_ROOM);
    cprintf(victim, "You have been blinded!\r\n");

    af.type = SPELL_BLINDNESS;
    af.location = APPLY_HITROLL;
    af.modifier = -4;					       /* Make hitroll worse */
    af.duration = dice((level / 5) + 1, 4);
    af.bitvector = AFF_BLIND;
    affect_to_char(victim, &af);
    af.location = APPLY_AC;
    af.modifier = +20;					       /* Make AC Worse! */
    affect_to_char(victim, &af);

    if ((!victim->specials.fighting) && (victim != ch))
	set_fighting(victim, ch);
}

void spell_burning_hands(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || level < 0 || level > ABS_MAX_LVL)
	return;
    dam = dice(1, 6) + MIN(level * 2, 30);

    if (dam < 1)
	dam = 1;

    cprintf(ch, "Searing flame fans out in front of you!\r\n");
    act("$n sends a fan of flame shooting from $s fingertips!\r\n", FALSE, ch, 0, 0, TO_ROOM);
    AreaEffectSpell(ch, dam, SPELL_BURNING_HANDS, 0, NULL);
}

void spell_call_lightning(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     added_dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (!CheckKill(ch, victim))
	return;

    dam = dice((level / 4) + 1, 6);
    added_dam = dice((level / 9) + 1, 8);

    if (IS_REALLY_VILE(ch) || IS_REALLY_HOLY(ch)
	|| (OUTSIDE(ch) && (weather_info.sky >= SKY_RAINING))) {
	if (saves_spell(victim, SAVING_SPELL))
	    dam >>= 1;
	dam += added_dam;
	damage(ch, victim, dam, SPELL_CALL_LIGHTNING);
    }
}

void spell_charm_person(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (victim == ch) {
	cprintf(ch, "You like yourself even better!\r\n");
	return;
    }
    if (!CheckKill(ch, victim))
	return;

    if (!IS_AFFECTED(victim, AFF_CHARM) && !IS_AFFECTED(ch, AFF_CHARM)) {
	if (circle_follow(victim, ch)) {
	    cprintf(ch, "Sorry, following in circles can not be allowed.\r\n");
	    return;
	}
	if (!IsPerson(victim)) {
	    cprintf(ch, "Umm,  that's not a person....\r\n");
	    return;
	}
	if (IsImmune(victim, IMM_CHARM)) {
	    FailCharm(victim, ch);
	    return;
	}
	if (IsResist(victim, IMM_CHARM)) {
	    if (saves_spell(victim, SAVING_PARA)) {
		FailCharm(victim, ch);
		return;
	    }
	    if (saves_spell(victim, SAVING_PARA)) {
		FailCharm(victim, ch);
		return;
	    }
	} else {
	    if (!IsSusc(victim, IMM_CHARM)) {
		if (saves_spell(victim, SAVING_PARA)) {
		    FailCharm(victim, ch);
		    return;
		}
	    }
	}

	if (victim->master)
	    stop_follower(victim);

	add_follower(victim, ch);

	af.type = SPELL_CHARM_PERSON;

	if (GET_INT(victim))
	    af.duration = 20 - GET_INT(victim);
	else
	    af.duration = 12;

	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(victim, &af);

	cprintf(ch, "They are now charmed.....\r\n");
	act("Isn't $n just such a nice fellow?", FALSE, ch, 0, victim, TO_VICT);
    }
}

void spell_chill_touch(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;
    int                                     dam = 0;
    int                                     lvl = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (!CheckKill(ch, victim))
	return;

    if (IsUndead(victim)) {
	if (!saves_spell(victim, SAVING_SPELL)) {
/* 
 * af.type      = SPELL_FEAR;
 * af.duration  = 4+level;
 * af.modifier  = 0;
 * af.location  = APPLY_NONE;
 * af.bitvector = 0;
 * affect_join(victim, &af, FALSE, FALSE);
 */
	    do_flee(victim, "", 0);
	}
	return;
    }
    lvl = GET_LEVEL(ch, MAGE_LEVEL_IND);
    dam = dice(((lvl + 1) / 2) - 1, 4);
    af.type = SPELL_CHILL_TOUCH;
    af.duration = lvl / 3;
    af.modifier = -1 - lvl / 20;
    af.location = APPLY_STR;
    af.bitvector = 0;
    affect_join(victim, &af, TRUE, FALSE);

    if (saves_spell(victim, SAVING_SPELL)) {
	dam = 0;
    }
    damage(ch, victim, dam, SPELL_CHILL_TOUCH);
}

/* First implementation attempt by Quixadhal, 95.12.05
 *
 * The basic idea is this:
 * We attempt to create an exact duplicate of player/mob X.
 *
 * If the target is in the room, there is a base 50/50 chance of sucess.
 * If the target makes a save vs. magic, then the spell fails.
 * If the target is not in the room, they get an additional save vs. magic to
 * determine if their items could be duplicated or not.  (IE: could the spell
 * divine the exact items the target had).
 * Each item also gets a saving throw for duplication... magical items will
 * be duplicated without the enchantment.  IE: an enchanted claymore which
 * was 1d10+4 would now be a normal 1d10 claymore.
 *
 * Once duplication is complete, the clone gets a save vs. paralysis to
 * determine if it remains under the caster's control.  If so, it acts like
 * a charmed monster until the duration expires.  If not, it will immediately
 * attack the caster, and then hunt down the copy of itself (if online).  Once
 * those are both dead, it will be a normal wandering aggressive monster.
 *
 * Note:  we must write a special routine to control this behaviour.
 */
void spell_clone(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    int                                     i = 0;
    int                                     diff = 0;
    int                                     chance = 0;
    int                                     snarl = 0;
    struct char_data                       *clone = NULL;
    struct affected_type                   *af = NULL;
    struct obj_data                        *tobj = NULL;
    struct follow_type                     *k = NULL;
    char                                    buf[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0";
    struct affected_type                    aff;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || (!victim && !obj) || level < 0 || level > ABS_MAX_LVL)
	return;

/* required object is a small glass mirror, #1133 */

    if (!victim) {
	cprintf(ch, "But whom do you wish to clone?\r\n");
	return;
    }
    if (IS_IMMORTAL(victim)) {
	cprintf(ch, "Nonononononono!  That would be suicide!!!!\r\n");
	return;
    }
    if (ch == victim) {
	cprintf(ch, "You don't like yourself enough to do this.\r\n");
	return;
    }
    if (IS_NPC(victim) && (victim->in_room != ch->in_room)
	&& (GetMaxLevel(victim) > (GetMaxLevel(ch) / 2))) {
	cprintf(ch, "You can't seem to get a solid lock on %s.\r\n", GET_SDESC(victim));
	return;
    }

    chance = 50;
    diff = GetMaxLevel(ch) - GetMaxLevel(victim);
    if (diff > 0)
	chance += 5 * diff;
    else
	chance -= 10 * diff;
    if (victim->in_room != ch->in_room)
	chance /= 2;
    chance = MIN(MAX(1, chance), 95);

    if (GetMaxLevel(ch) < LOKI) {
	cprintf(ch, "Sorry!  Clone is not quite ready yet.\r\n");
	cprintf(ch, "You would have a %d%% chance of it working though!\r\n", chance);
	return;
    }

    if (number(1, 100) > chance) {
	cprintf(ch, "You fail miserably, and scrape glass from your scalp.\r\n");
	act("$n bitches and moans as the spell fizzles.", FALSE, ch, 0, 0, TO_ROOM);
	return;
    }
    CREATE(clone, struct char_data, 1);
    clear_char(clone);
    clone->nr = victim->nr;				       /* this may get changed later */
    clone->in_room = ch->in_room;			       /* summons clone to caster, normally */
    clone->mail = NULL;
    clone->immune = victim->immune;
    clone->M_immune = victim->M_immune;
    clone->susc = victim->susc;
    clone->mult_att = victim->mult_att;
    clone->attackers = 0;				       /* no one is fighting us, yet... */
    clone->fallspeed = 0;				       /* used when falling? */
    clone->race = victim->race;
    clone->hunt_dist = victim->hunt_dist;
    clone->hatefield = victim->hatefield;
    clone->fearfield = victim->fearfield;
    clone->hates = victim->hates;
    clone->hates.clist = NULL;				       /* don't duplicate the whole list */
    clone->fears = victim->fears;
    clone->fears.clist = NULL;				       /* don't duplicate the whole list */
    clone->persist = victim->persist;
    clone->old_room = victim->old_room;
    clone->act_ptr = victim->act_ptr;
    clone->player = victim->player;
    if (victim->player.name)
	clone->player.name = strdup(victim->player.name);
    if (victim->player.short_descr)
	clone->player.short_descr = strdup(victim->player.short_descr);
    else
	clone->player.short_descr = strdup(clone->player.name);
    if (victim->player.long_descr)
	clone->player.long_descr = strdup(victim->player.long_descr);
    else {
	CREATE(clone->player.long_descr, char,
	       strlen(victim->player.name) + strlen(victim->player.title) + 22);
	strcpy(clone->player.long_descr, victim->player.name);
	strcat(clone->player.long_descr, " ");
	strcat(clone->player.long_descr, victim->player.title);
	strcat(clone->player.long_descr, " is standing here.\r\n");
    }
    if (victim->player.description)
	clone->player.description = strdup(victim->player.description);
    if (victim->player.pre_title)
	clone->player.pre_title = strdup(victim->player.pre_title);
    if (victim->player.title)
	clone->player.title = strdup(victim->player.title);
    if (victim->player.poof_in)
	clone->player.poof_in = strdup(victim->player.poof_in);
    if (victim->player.poof_out)
	clone->player.poof_out = strdup(victim->player.poof_out);
    if (victim->player.guild_name)
	clone->player.guild_name = strdup(victim->player.guild_name);
    if (victim->player.sounds)
	clone->player.sounds = strdup(victim->player.sounds);
    if (victim->player.distant_snds)
	clone->player.distant_snds = strdup(victim->player.distant_snds);
    clone->abilities = victim->abilities;
    clone->tmpabilities = victim->tmpabilities;
    clone->points = victim->points;
    clone->specials = victim->specials;
    clone->specials.fighting = NULL;
    clone->specials.hunting = NULL;			       /* later, we hunt our original */
    clone->specials.mounted_on = NULL;
    clone->specials.ridden_by = NULL;
    for (i = 0; i < MAX_SKILLS; i++)
	clone->skills[i] = victim->skills[i];
    for (af = victim->affected; af; af = af->next)
	affect_to_char(clone, af);
/* struct obj_data *equipment[MAX_WEAR] */
    for (i = 0; i < MAX_WEAR; i++)
	if (victim->equipment[i]) {
	    if (number(1, 100) > chance) {
		continue;
	    }
	    if (!(tobj = read_object(victim->equipment[i]->item_number, REAL)))
		continue;
	    /*
	     * obj_to_char(obj, clone); 
	     */
	    tobj->carried_by = NULL;
	    tobj->in_room = NOWHERE;
	    clone->equipment[i] = tobj;
	    tobj->equipped_by = clone;
	    tobj->eq_pos = i;
	} else
	    clone->equipment[i] = NULL;
/* struct obj_data *carrying */
    clone->carrying = NULL;
    clone->desc = NULL;
    clone->next_in_room = NULL;
    clone->next = NULL;
    clone->next_fighting = NULL;
    clone->followers = NULL;
    clone->master = NULL;
    clone->invis_level = 0;

/* now we are copied... let's fix things */
    GET_GOLD(clone) = 1;
    GET_BANK(clone) = 0;
    GET_EXP(clone) = GetMaxLevel(clone) * 100;

/* make sure they are now an NPC */
    if (IS_NPC(clone))
	mob_index[clone->nr].number++;
    else {
	clone->nr = -1;
	SET_BIT(clone->specials.act, ACT_ISNPC);
    }
/* make them hate the original they were cloned from */
    AddHated(clone, victim);

/* make them aggressive */
    SET_BIT(clone->specials.act, ACT_AGGRESSIVE);
    SET_BIT(clone->specials.act, ACT_SCAVENGER);
    SET_BIT(clone->specials.act, ACT_USE_ITEM);
    SET_BIT(clone->specials.new_act, NEW_PLR_KILLOK);

/* add them to the world character list */
    clone->next = character_list;
    character_list = clone;

    snarl = 0;
/* now make them be charmed */
    if (ch->in_room != victim->in_room)
	if (number(1, 100) > chance) {
	    char_to_room(clone, ch->in_room);
	    FailCharm(clone, ch);
	    snarl = 1;
	}
    if (circle_follow(clone, ch)) {
	char_to_room(clone, ch->in_room);
	FailCharm(clone, ch);
	snarl = 1;
    }
    if (IsImmune(clone, IMM_CHARM)) {
	char_to_room(clone, ch->in_room);
	FailCharm(clone, ch);
	snarl = 1;
    }
    if (IsResist(clone, IMM_CHARM)) {
	if (saves_spell(clone, SAVING_PARA)) {
	    char_to_room(clone, ch->in_room);
	    FailCharm(clone, ch);
	    snarl = 1;
	}
    } else {
	if (!IsSusc(clone, IMM_CHARM)) {
	    if (number(1, 100) > chance) {
		char_to_room(clone, ch->in_room);
		FailCharm(clone, ch);
		snarl = 1;
	    }
	} else {
	    if (number(1, 100) > MAX(chance + chance / 2, 97)) {
		char_to_room(clone, ch->in_room);
		FailCharm(clone, ch);
		snarl = 1;
	    }
	}
    }
    if (!snarl) {
	clone->master = ch;
	CREATE(k, struct follow_type, 1);

	k->follower = clone;
	k->next = ch->followers;
	ch->followers = k;

	aff.type = SPELL_CHARM_PERSON;
	if (GET_INT(clone))
	    aff.duration = MAX(1, GET_LEVEL(ch, BestMagicClass(ch)) - GET_INT(clone));
	else
	    aff.duration = 6;
	aff.modifier = 0;
	aff.location = 0;
	aff.bitvector = AFF_CHARM;
	affect_to_char(clone, &aff);

	char_to_room(clone, ch->in_room);
    }
    if (IS_PC(victim)) {
	cprintf(ch, "You create a duplicate of %s.\r\n", GET_NAME(victim));
	sprintf(buf, "$n creates a duplicate of %s.", GET_NAME(victim));
    } else {
	cprintf(ch, "You create a duplicate of %s.\r\n", GET_SDESC(victim));
	sprintf(buf, "$n creates a duplicate of %s.", GET_SDESC(victim));
    }
    act("%s", FALSE, ch, 0, 0, TO_ROOM, buf);
    if (snarl) {
	if (IS_PC(victim)) {
	    cprintf(ch, "%s turns to you and snarls.\r\n", GET_NAME(victim));
	    sprintf(buf, "%s snarls at $n.", GET_NAME(victim));
	} else {
	    cprintf(ch, "%s turns to you and snarls.\r\n", GET_SDESC(victim));
	    sprintf(buf, "%s snarls at $n.", GET_SDESC(victim));
	}
	act("%s", FALSE, ch, 0, 0, TO_ROOM, buf);
    }
}

void spell_colour_spray(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     dam = 0;
    struct char_data                       *tmp_victim = NULL;
    struct char_data                       *temp = NULL;
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || level < 0 || level > ABS_MAX_LVL)
	return;

    dam = dice(1, 6);

    for (tmp_victim = character_list; tmp_victim; tmp_victim = temp) {
	temp = tmp_victim->next;
	if ((ch->in_room == tmp_victim->in_room) &&
	    (ch != tmp_victim) &&
	    (!((IS_AFFECTED(tmp_victim, AFF_GROUP) && (((tmp_victim == ch->master)
							|| (tmp_victim->master == ch)
							|| (tmp_victim->master ==
							    ch->master))))))
	    && CheckKill(ch, tmp_victim)) {
	    if (IS_PC(tmp_victim) && IS_IMMORTAL(tmp_victim) && !IS_IMMORTAL(ch)) {
		cprintf(tmp_victim, "Some puny mortal tries to blind you with color spray\r\n");
	    } else {
		damage(ch, tmp_victim, dam, SPELL_COLOUR_SPRAY);

		if (GetMaxLevel(tmp_victim) <= (GET_LEVEL(ch, MAGE_LEVEL_IND) / 2)) {
		    if (!saves_spell(tmp_victim, SAVING_SPELL)) {
			if (!affected_by_spell(tmp_victim, SPELL_PARALYSIS)) {
			    act("$n is captivated by the brilliance of the rays!", TRUE,
				tmp_victim, 0, 0, TO_ROOM);
			    cprintf(tmp_victim,
				    "You cannot take your gaze from the brilliant ray!\r\n");
			    af.type = SPELL_PARALYSIS;
			    af.duration = dice(1, 6);
			    af.modifier = 0;
			    af.location = APPLY_NONE;
			    af.bitvector = AFF_PARALYSIS;
			    affect_join(tmp_victim, &af, FALSE, FALSE);

			    if ((!tmp_victim->specials.fighting) && (tmp_victim != ch))
				set_fighting(tmp_victim, ch);
			}
		    }
		} else if (GetMaxLevel(tmp_victim) <= (GET_LEVEL(ch, MAGE_LEVEL_IND) + 3)) {
		    if (!saves_spell(tmp_victim, SAVING_SPELL)) {
			if (!affected_by_spell(tmp_victim, SPELL_BLINDNESS)) {
			    act("$n fumbles in the brilliance of the rays!", TRUE, tmp_victim,
				0, 0, TO_ROOM);
			    cprintf(tmp_victim,
				    "You have been blinded by a brilliant ray!\r\n");
			    af.type = SPELL_BLINDNESS;
			    af.location = APPLY_HITROLL;
			    af.modifier = -4;
			    af.duration = dice(2, 4);
			    af.bitvector = AFF_BLIND;
			    affect_to_char(tmp_victim, &af);
			    af.location = APPLY_AC;
			    af.modifier = +20;		       /* Make AC Worse! */
			    affect_to_char(tmp_victim, &af);

			    if ((!tmp_victim->specials.fighting) && (tmp_victim != ch))
				set_fighting(tmp_victim, ch);
			}
		    }
		}
	    }
	}
    }
}

void spell_control_weather(char level, struct char_data *ch, struct char_data *victim,
			   struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
    /*
     * Control Weather is not possible here!!! 
     */
    /*
     * Better/Worse can not be transferred 
     */
}

void spell_create_food(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct obj_data                        *tmp_obj = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || level < 0 || level > ABS_MAX_LVL)
	return;
    CREATE(tmp_obj, struct obj_data, 1);

    clear_object(tmp_obj);

    if (number(0, 99) < 20) {
	tmp_obj->name = (char *)strdup("dung shit");
	tmp_obj->short_description = (char *)strdup("Some Dried Dung");
	tmp_obj->description =
	    (char *)strdup("A noxious smelling, but edible, buffalo chip sits here.");
    } else if (number(0, 99) < 40) {
	tmp_obj->name = (char *)strdup("cookie");
	tmp_obj->short_description = (char *)strdup("A Cookie");
	tmp_obj->description =
	    (char *)strdup("A crisp cookie with strawberry filling waits for you here!");
    } else {
	tmp_obj->name = (char *)strdup("mushroom");
	tmp_obj->short_description = (char *)strdup("A Magic Mushroom");
	tmp_obj->description =
	    (char *)strdup("A really delicious looking magic mushroom lies here.");
    }

    tmp_obj->obj_flags.type_flag = ITEM_FOOD;
    tmp_obj->obj_flags.wear_flags = ITEM_TAKE | ITEM_HOLD;
    tmp_obj->obj_flags.value[0] = 5 + level;
    tmp_obj->obj_flags.weight = 1;
    tmp_obj->obj_flags.cost = 10;
    tmp_obj->obj_flags.cost_per_day = 1;

    tmp_obj->next = object_list;
    object_list = tmp_obj;
    obj_to_room(tmp_obj, ch->in_room);
    tmp_obj->item_number = -1;
    act("$p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_ROOM);
    act("$p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_CHAR);
}

void spell_create_water(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     water = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !obj || level < 0 || level > ABS_MAX_LVL)
	return;
    if (GET_ITEM_TYPE(obj) == ITEM_DRINKCON) {
	if ((obj->obj_flags.value[2] != LIQ_WATER) && (obj->obj_flags.value[1] != 0)) {
	    name_from_drinkcon(obj);
	    obj->obj_flags.value[2] = LIQ_SLIME;
	    name_to_drinkcon(obj, LIQ_SLIME);
	} else {
	    water = 2 * level * ((weather_info.sky >= SKY_RAINING) ? 2 : 1);
	    /*
	     * Calculate water it can contain, or water created 
	     */
	    water = MIN(obj->obj_flags.value[0] - obj->obj_flags.value[1], water);

	    if (water > 0) {
		obj->obj_flags.value[2] = LIQ_WATER;
		obj->obj_flags.value[1] += water;

		weight_change_object(obj, water);

		name_from_drinkcon(obj);
		name_to_drinkcon(obj, LIQ_WATER);
		act("$p is partially filled.", FALSE, ch, obj, 0, TO_CHAR);
	    }
	}
    }
}

void spell_cure_blind(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (affected_by_spell(victim, SPELL_BLINDNESS)) {
	affect_from_char(victim, SPELL_BLINDNESS);
	cprintf(victim, "Your vision returns!\r\n");
    }
}

/* Offensive Spells */

void spell_magic_missile(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     missiles = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;

    if (!CheckKill(ch, victim))
	return;

    missiles = (GET_LEVEL(ch, MAGE_LEVEL_IND) / 2) + 1;
    missiles = MIN(5, missiles);
    dam = dice(missiles, 4) + missiles;

    if (affected_by_spell(victim, SPELL_SHIELD))
	dam = 0;

    damage(ch, victim, dam, SPELL_MAGIC_MISSILE);
}

void spell_shocking_grasp(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     classes = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (!CheckKill(ch, victim))
	return;

    classes = HowManyClasses(ch);

    dam = dice(1, 8) + level;

    if (classes > 1)
	dam -= dice(classes, 3);

    if (dam < 1)
	dam = 1;

    if (saves_spell(victim, SAVING_SPELL))
	dam >>= 1;
    damage(ch, victim, dam, SPELL_SHOCKING_GRASP);
}

void spell_lightning_bolt(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     high_die = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0)
	return;
    if (!CheckKill(ch, victim))
	return;

    high_die = ((level / 10) + (level / 3) + 1);
    dam = dice(high_die, 6);

    if (saves_spell(victim, SAVING_SPELL))
	dam /= 2;

    damage(ch, victim, dam, SPELL_LIGHTNING_BOLT);
}

/* Drain XP, MANA, HP - caster gains HP and MANA */
void spell_energy_drain(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0)
	return;

    if (!CheckKill(ch, victim))
	return;
    if (!saves_spell(victim, SAVING_SPELL)) {
	if (IS_GOOD(ch) && IS_EVIL(victim) && IS_NPC(victim)) {
	    GET_ALIGNMENT(ch) += 100;
	    if (GET_ALIGNMENT(ch) > 1000)
		GET_ALIGNMENT(ch) = 1000;
	}
	if (IS_EVIL(ch) && IS_GOOD(victim) && IS_NPC(victim)) {
	    GET_ALIGNMENT(ch) -= 100;
	    if (GET_ALIGNMENT(ch) < -1000)
		GET_ALIGNMENT(ch) = -1000;
	}
	if (IS_PC(victim))
	    GET_ALIGNMENT(ch) = -1000;

	if (GetMaxLevel(victim) <= 1) {
	    damage(ch, victim, 100, SPELL_ENERGY_DRAIN);       /* Kill the sucker */
	} else if (IS_PC(victim) && IS_IMMORTAL(victim) && !IS_IMMORTAL(ch)) {
	    cprintf(victim, "Some puny mortal just tried to drain you...\r\n");
	} else {
	    if (IS_NOT_SET(victim->M_immune, IMM_DRAIN)) {
		cprintf(victim, "Your life energy is drained!\r\n");
		dam = 1;
		if (IS_PC(victim)) {
		    if (GetMaxLevel(ch) < GetMaxLevel(victim))
			gain_exp(ch, GET_EXP(victim) / (dice(1, 4) * 1000));
		    ch->points.hit += dice(1, 4);
		    damage(ch, victim, dam, SPELL_ENERGY_DRAIN);
		    drop_level(victim, BestClass(victim));
		    set_title(victim);
		} else {
		    dam = dice(MIN((level / 5), 9), 4);
		    damage(ch, victim, dam, SPELL_ENERGY_DRAIN);
		}
	    } else {
		if (IS_NOT_SET(ch->M_immune, IMM_DRAIN)) {
		    cprintf(ch, "Your spell backfires!\r\n");
		    if (IS_PC(ch) && !IS_IMMORTAL(ch)) {
			drop_level(ch, BestClass(ch));
			set_title(ch);
		    } else {
			dam = dice(MIN((level / 5), 9), 8);    /* nasty spell */
			damage(ch, victim, dam, SPELL_ENERGY_DRAIN);
		    }
		} else {
		    cprintf(ch, "Your spell fails utterly.\r\n");
		}
	    }
	}
    } else {
	damage(ch, victim, 0, SPELL_ENERGY_DRAIN);	       /* Miss */
    }
}

void spell_fireball(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     high_die = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || level < 0 || level > ABS_MAX_LVL)
	return;
    high_die = (level / 3) + 2;
    dam = dice(high_die, 6);

    AreaEffectSpell(ch, dam, SPELL_FIREBALL, 1, "You feel a blast of hot air.\r\n");
}

void spell_new_earthquake(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     i = 0;
    int                                     localdamage = 0;
    int                                     neardamage = 0;
    int                                     found = FALSE;
    struct room_data                       *here = NULL;
    struct room_data                       *tmp = NULL;
    struct room_direction_data             *exitdata = NULL;
    struct char_data                       *tvictim = NULL;
    struct char_data                       *next_victim = NULL;
    struct room_data                       *rp[MAX_NUM_EXITS];

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || level < 0 || level > ABS_MAX_LVL)
	return;
    localdamage = dice(level, 4);
    neardamage = dice(level / 4, 4);
    if (!ch->in_room)
	return;
    if (!(here = real_roomp(ch->in_room)))
	return;
    for (i = 0; i < MAX_NUM_EXITS; i++)
	if ((exitdata = EXIT(ch, i)))
	    rp[i] = real_roomp(exitdata->to_room);
    for (tvictim = character_list; tvictim; tvictim = next_victim) {
	next_victim = tvictim->next;
	if (!tvictim || !tvictim->in_room)
	    continue;
	if (tvictim == ch)
	    continue;
	if (IS_IMMORTAL(tvictim) && !IS_IMMORTAL(ch)) {
	    cprintf(tvictim, "The ground shakes a bit as the mortals play.\r\n");
	    continue;
	}
	if (!CheckKill(ch, tvictim))
	    continue;
	if (IS_AFFECTED(tvictim, AFF_GROUP))
	    if ((tvictim == ch->master) || (tvictim->master == ch)
		|| (tvictim->master == ch->master))
		continue;
	if (tvictim->in_room == ch->in_room) {		       /* full SUFFERAGE! */
	    damage(ch, tvictim, localdamage, SPELL_EARTHQUAKE);
	    act("You fall and are pummled with debris!\r\n", FALSE, ch, 0, tvictim, TO_VICT);
	    if (GET_POS(tvictim) > POSITION_SITTING)
		GET_POS(tvictim) = POSITION_SITTING;
	    if (GET_POS(tvictim) > POSITION_DEAD) {
		WAIT_STATE(tvictim, (PULSE_VIOLENCE * 3));
		if (IS_MOB(tvictim))
		    AddHated(tvictim, ch);
	    }
	} else {
	    if (!(tmp = real_roomp(tvictim->in_room)))
		continue;
	    found = FALSE;
	    for (i = 0; i < MAX_NUM_EXITS; i++) {
		if (rp[i] && tmp->number == rp[i]->number) {   /* adjacent rooms SUFFER! */
		    found = TRUE;
		    damage(tvictim, tvictim, neardamage, SPELL_EARTHQUAKE);
		    act("The ground shakes nearby and you lose your footing!\r\n",
			FALSE, tvictim, 0, tvictim, TO_VICT);
		    if (GET_POS(tvictim) > POSITION_SITTING)
			GET_POS(tvictim) = POSITION_SITTING;
		    if (GET_POS(tvictim) > POSITION_DEAD) {
			WAIT_STATE(tvictim, (PULSE_VIOLENCE));
			if (IS_MOB(tvictim))
			    AddHated(tvictim, ch);
		    }
		    break;
		}
	    }
	    if (!found) {
		if (here->zone == tmp->zone) {		       /* Well, tell them it moved for them */
		    act("The ground quivers all around you...\r\n", FALSE, tvictim, 0, tvictim,
			TO_VICT);
		}
	    }
	}
    }
}

void spell_earthquake(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || level < 0 || level > ABS_MAX_LVL)
	return;
    dam = dice(1, 8) + level;

    cprintf(ch, "The ground trembles beneath your feet!\r\n");
    act("$n makes the ground tremble and shiver\r\n", FALSE, ch, 0, 0, TO_ROOM);
    AreaEffectSpell(ch, dam, SPELL_EARTHQUAKE, 1,
		    "The ground trembless beneath your feet....\r\n");
}

void spell_dispel_evil(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (!CheckKill(ch, victim))
	return;

    if (IsExtraPlanar(victim)) {
	if (IS_EVIL(ch)) {
	    victim = ch;
	} else {
	    if (IS_GOOD(victim)) {
		act("Good protects $N.", FALSE, ch, 0, victim, TO_CHAR);
		return;
	    }
	}

	if (!saves_spell(victim, SAVING_SPELL)) {
	    act("$n forces $N from this plane.", TRUE, ch, 0, victim, TO_ROOM);
	    act("You force $N from this plane.", TRUE, ch, 0, victim, TO_CHAR);
	    act("$n forces you from this plane.", TRUE, ch, 0, victim, TO_VICT);
	    gain_exp(ch, MIN(GET_EXP(victim) / 2, 50000));
	    extract_char(victim);
	}
    } else {
	act("$N laughs at you.", TRUE, ch, 0, victim, TO_CHAR);
	act("$N laughs at $n.", TRUE, ch, 0, victim, TO_NOTVICT);
	act("You laugh at $n.", TRUE, ch, 0, victim, TO_VICT);
    }
}

void spell_harm(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;

    if (!CheckKill(ch, victim))
	return;

    dam = (2 * GET_LEVEL(ch, CLERIC_LEVEL_IND));

    if (IS_REALLY_HOLY(ch))
	dam = (GET_LEVEL(ch, CLERIC_LEVEL_IND));
    else if (IS_REALLY_VILE(ch))
	dam = MIN(200, GET_HIT(victim)) - dice(1, 4);

    if (dam < 1)
	dam = 1;

    if (saves_spell(victim, SAVING_SPELL))
	dam = (2 * GET_LEVEL(ch, CLERIC_LEVEL_IND));

    damage(ch, victim, dam, SPELL_HARM);
}

/* spells2.c - Not directly offensive spells */

void spell_shelter(char level, struct char_data *ch, struct char_data *victim,
		   struct obj_data *obj)
{
    struct obj_cost                         cost;
    int                                     i = 0;
    int                                     save_room = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || level < 0 || level > ABS_MAX_LVL)
	return;
    if (IS_NPC(ch))
	return;

    cost.total_cost = 0;				       /* Minimum cost */
    cost.no_carried = 0;
    cost.ok = TRUE;					       /* Use if any "-1" objects */

    add_obj_cost(ch, 0, ch->carrying, &cost);

    for (i = 0; i < MAX_WEAR; i++)
	add_obj_cost(ch, 0, ch->equipment[i], &cost);

    if (!cost.ok)
	return;

    obj_from_char(obj);
    extract_obj(obj);
    cost.total_cost = 0;

    GET_HOME(ch) = ch->in_room;
    new_save_equipment(ch, &cost, FALSE);
    save_obj(ch, &cost, 1);
    save_room = ch->in_room;
    cprintf(ch, "You open a small rip in the fabric of space!\r\n");
    cprintf(ch, "As you step through you leave the world of WileyMUD III behind....\r\n");
    act("$n opens a small rip in the fabric of space and steps through!", FALSE, ch, 0, 0,
	TO_ROOM);
    extract_char(ch);
    ch->in_room = save_room;
    save_char(ch, ch->in_room);
    return;
}

void spell_astral_walk(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     location = 0;
    struct room_data                       *rp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;
    location = victim->in_room;
    rp = real_roomp(location);

    if (!rp || IS_SET(rp->room_flags, PRIVATE) ||
	IS_SET(rp->room_flags, NO_SUM) || IS_SET(rp->room_flags, NO_MAGIC)) {
	cprintf(ch, "You failed.\r\n");
	return;
    }
    if (dice(1, 8) == 8) {
	cprintf(ch, "You failed.\r\n");
	return;
    } else {
	act("$n opens a door to another dimension and steps through!", FALSE, ch, 0, 0,
	    TO_ROOM);
	char_from_room(ch);
	char_to_room(ch, location);
	do_look(ch, "", 15);
	act("You are blinded for a moment as $n appears in a flash of light!", FALSE, ch, 0, 0,
	    TO_ROOM);
	do_look(ch, "", 15);
    }
}

void spell_visions(char level, struct char_data *ch, struct char_data *victim,
		   struct obj_data *obj)
{
    int                                     location = 0;
    int                                     orig_loc = 0;
    struct room_data                       *rp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || level < 0 || level > ABS_MAX_LVL)
	return;
    location = victim->in_room;

    rp = real_roomp(location);

    if (!rp || IS_SET(rp->room_flags, PRIVATE) || IS_SET(rp->room_flags, NO_MAGIC)) {
	cprintf(ch, "A magical boundary obstructs your vision.\r\n");
	return;
    }
    if (dice(1, 8) == 8) {
	cprintf(ch, "You could not receive a vision.\r\n");
	return;
    } else {
	orig_loc = ch->in_room;
	char_from_room(ch);
	char_to_room(ch, location);
	cprintf(ch, "You see in your mind's eye...\r\n");
	do_look(ch, "", 15);
	char_from_room(ch);
	char_to_room(ch, orig_loc);
    }
}

void spell_cure_critic(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     healpoints = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (HowManyClasses(ch) == 1)
	healpoints = dice(3, 8) + 3;
    else
	healpoints = dice(3, 7);

    if (IS_REALLY_HOLY(ch))
	healpoints += dice(1, 5);
    else if (IS_REALLY_VILE(ch))
	healpoints -= dice(1, 5);
    else if (IS_HOLY(ch))
	healpoints += dice(1, 3);
    else if (IS_VILE(ch))
	healpoints -= dice(1, 3);

    if (healpoints < 1)
	healpoints = 1;

    if ((healpoints + GET_HIT(victim)) > hit_limit(victim))
	GET_HIT(victim) = hit_limit(victim);
    else
	GET_HIT(victim) += healpoints;

    cprintf(victim, "You feel better!\r\n");
    update_pos(victim);
    if (ch)
	cprintf(ch, "%s %s.\r\n", NAME(victim), pain_level(victim));
}

void spell_cure_light(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    int                                     healpoints = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (HowManyClasses(ch) == 1)
	healpoints = dice(2, 4) + 1;
    else
	healpoints = dice(1, 8);

    if (IS_REALLY_HOLY(ch))
	healpoints += dice(1, 2);
    else if (IS_REALLY_VILE(ch))
	healpoints -= dice(1, 2);
    else if (IS_HOLY(ch))
	healpoints += 1;
    else if (IS_VILE(ch))
	healpoints -= 1;

    if (healpoints < 1)
	healpoints = 1;

    if ((healpoints + GET_HIT(victim)) > hit_limit(victim))
	GET_HIT(victim) = hit_limit(victim);
    else
	GET_HIT(victim) += healpoints;

    cprintf(victim, "You feel better!\r\n");
    update_pos(victim);
    if (ch)
	cprintf(ch, "%s %s.\r\n", NAME(victim), pain_level(victim));
}

void spell_curse(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if ((!victim && !obj) || level < 0 || level > ABS_MAX_LVL)
	return;
    if (obj) {
	SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_GOOD);
	SET_BIT(obj->obj_flags.extra_flags, ITEM_NODROP);

	/*
	 * LOWER ATTACK DICE BY -1 
	 */
	if (obj->obj_flags.type_flag == ITEM_WEAPON) {
	    obj->obj_flags.value[2]--;
	    if (obj->obj_flags.value[2] < 0)
		obj->obj_flags.value[2] = 0;
	}
	act("$p glows red.", FALSE, ch, obj, 0, TO_CHAR);
    } else {
	if (saves_spell(victim, SAVING_SPELL) || affected_by_spell(victim, SPELL_CURSE)) {
	    if (IS_NPC(victim) && !victim->specials.fighting)
		set_fighting(victim, ch);
	    return;
	}
	af.type = SPELL_CURSE;
	af.duration = 24;
	af.modifier = -1;
	af.location = APPLY_HITROLL;
	af.bitvector = AFF_CURSE;
	affect_to_char(victim, &af);

	af.location = APPLY_SAVING_PARA;
	af.modifier = 1;				       /* Make worse */
	affect_to_char(victim, &af);

	act("$n briefly reveals a red aura!", FALSE, victim, 0, 0, TO_ROOM);
	if (IS_NPC(victim) && !victim->specials.fighting) {
	    set_fighting(victim, ch);
	    return;
	}
	act("You feel very uncomfortable.", FALSE, victim, 0, 0, TO_CHAR);
    }
}

void spell_detect_evil(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;
    int                                     dur = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (affected_by_spell(victim, SPELL_DETECT_EVIL))
	return;

    dur = 20;

    if (IS_REALLY_HOLY(ch))
	dur += dice(1, 8);
    else if (IS_REALLY_VILE(ch))
	dur -= dice(1, 8);
    else if (IS_HOLY(ch))
	dur += dice(1, 4);
    else if (IS_VILE(ch))
	dur -= dice(1, 4);

    af.type = SPELL_DETECT_EVIL;
    af.duration = dur;
    af.modifier = 0;
    af.location = APPLY_NONE;
    af.bitvector = AFF_DETECT_EVIL;
    affect_to_char(victim, &af);
    act("$n's eyes briefly glow bright white", FALSE, victim, 0, 0, TO_ROOM);
    cprintf(victim, "Your eyes tingle.\r\n");
}

void spell_detect_invisibility(char level, struct char_data *ch, struct char_data *victim,
			       struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (affected_by_spell(victim, SPELL_DETECT_INVISIBLE))
	return;

    af.type = SPELL_DETECT_INVISIBLE;
    af.duration = 5 + level;
    af.modifier = 0;
    af.location = APPLY_NONE;
    af.bitvector = AFF_DETECT_INVISIBLE;

    affect_to_char(victim, &af);
    act("$n's eyes briefly glow yellow", FALSE, victim, 0, 0, TO_ROOM);
    cprintf(victim, "Your eyes tingle.\r\n");
}

void spell_detect_magic(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || level < 0 || level > ABS_MAX_LVL)
	return;
    if (affected_by_spell(victim, SPELL_DETECT_MAGIC))
	return;

    af.type = SPELL_DETECT_MAGIC;
    af.duration = 2 + level;
    af.modifier = 0;
    af.location = APPLY_NONE;
    af.bitvector = AFF_DETECT_MAGIC;

    affect_to_char(victim, &af);
    cprintf(victim, "Your eyes tingle.\r\n");
}

void spell_detect_poison(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || (!victim && !obj) || level < 0 || level > ABS_MAX_LVL)
	return;
    if (victim) {
	if (victim == ch)
	    if (IS_AFFECTED(victim, AFF_POISON))
		cprintf(ch, "You can sense poison in your blood.\r\n");
	    else
		cprintf(ch, "You feel healthy.\r\n");
	else if (IS_AFFECTED(victim, AFF_POISON)) {
	    act("You sense that $E is poisoned.", FALSE, ch, 0, victim, TO_CHAR);
	} else {
	    act("You sense that $E is poisoned", FALSE, ch, 0, victim, TO_CHAR);
	}
    } else {						       /* It's an object */
	if ((obj->obj_flags.type_flag == ITEM_DRINKCON)
	    || (obj->obj_flags.type_flag == ITEM_FOOD)) {
	    if (obj->obj_flags.value[3])
		act("Poisonous fumes are revealed.", FALSE, ch, 0, 0, TO_CHAR);
	    else
		cprintf(ch, "It looks very delicious.\r\n");
	}
    }
}

void spell_enchant_weapon(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     i = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !obj)
	return;
    if ((GET_ITEM_TYPE(obj) == ITEM_WEAPON)
	&& IS_NOT_SET(obj->obj_flags.extra_flags, ITEM_MAGIC)) {
	for (i = 0; i < MAX_OBJ_AFFECT; i++)
	    if (obj->affected[i].location != APPLY_NONE)
		return;

	SET_BIT(obj->obj_flags.extra_flags, ITEM_MAGIC);
	obj->affected[0].location = APPLY_HITROLL;
	obj->affected[0].modifier = 1;
	if (level > 20)
	    obj->affected[0].modifier += 1;
	if (level > 40)
	    obj->affected[0].modifier += 1;
	if (level > MAX_MORT)
	    obj->affected[0].modifier += 1;

	obj->affected[1].location = APPLY_DAMROLL;
	obj->affected[1].modifier = 1;
	if (level > 15)
	    obj->affected[1].modifier += 1;
	if (level > 30)
	    obj->affected[1].modifier += 1;
	if (level > MAX_MORT)
	    obj->affected[1].modifier += 1;

	if (IS_GOOD(ch)) {
	    SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_EVIL);
	    act("$p glows blue.", FALSE, ch, obj, 0, TO_CHAR);
	} else if (IS_EVIL(ch)) {
	    SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_GOOD);
	    act("$p glows red.", FALSE, ch, obj, 0, TO_CHAR);
	} else {
	    act("$p glows yellow.", FALSE, ch, obj, 0, TO_CHAR);
	}
    }
}

void spell_heal(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;

    dam = (2 * GET_LEVEL(ch, CLERIC_LEVEL_IND));

    if (IS_REALLY_HOLY(ch))
	dam = MIN(200, GET_HIT(ch)) - dice(1, 4);
    else if (IS_REALLY_VILE(ch))
	dam = GET_LEVEL(ch, CLERIC_LEVEL_IND);

    if (HowManyClasses(ch) > 1)
	dam -= dice(HowManyClasses(ch), 4);

    if (dam < 1)
	dam = 1;

    GET_HIT(victim) += dam;

    if (GET_HIT(victim) >= hit_limit(victim))
	GET_HIT(victim) = hit_limit(victim) - dice(1, 4);

    update_pos(victim);
    cprintf(victim, "A deity has smiled down on you....\r\n");
}

void spell_invisibility(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || (!ch && !obj))
	return;

    if (obj) {
	if (!IS_SET(obj->obj_flags.extra_flags, ITEM_INVISIBLE)) {
	    act("$p turns invisible.", FALSE, ch, obj, 0, TO_CHAR);
	    act("$p turns invisible.", TRUE, ch, obj, 0, TO_ROOM);
	    SET_BIT(obj->obj_flags.extra_flags, ITEM_INVISIBLE);
	}
    } else {						       /* Then it is a PC | NPC */
	if (!affected_by_spell(victim, SPELL_INVISIBLE)) {
	    act("$n slowly fades out of existence.", TRUE, victim, 0, 0, TO_ROOM);
	    cprintf(victim, "You vanish.\r\n");
	    af.type = SPELL_INVISIBLE;
	    af.duration = 1 + (level / 2);
	    af.modifier = -40;
	    af.location = APPLY_AC;
	    af.bitvector = AFF_INVISIBLE;
	    affect_to_char(victim, &af);
	}
    }
}

void spell_locate_object(char level, struct char_data *ch, struct char_data *victim, char *obj)
{
    struct obj_data                        *i = NULL;
    char                                    name[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    int                                     j = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), VNULL(obj));

    if (!ch || !obj)
	return;

    strcpy(name, obj);
    j = level >> 1;

    for (i = object_list; i && (j > 0); i = i->next)
	if (isname(name, i->name)) {
	    if (i->carried_by) {
		if (strlen(PERS(i->carried_by, ch)) > 0) {
		    cprintf(ch, "%s carried by %s.\r\n", i->short_description,
			    PERS(i->carried_by, ch));
		}
	    } else if (i->equipped_by) {
		if (strlen(PERS(i->equipped_by, ch)) > 0) {
		    cprintf(ch, "%s equipped by %s.\r\n", i->short_description,
			    PERS(i->equipped_by, ch));
		}
	    } else if (i->in_obj) {
		cprintf(ch, "%s in %s.\r\n", i->short_description,
			i->in_obj->short_description);
	    } else {
		cprintf(ch, "%s in %s.\r\n", i->short_description,
			(i->in_room ==
			 NOWHERE ? "use but uncertain." : real_roomp(i->in_room)->name));
		j--;
	    }
	}
    if (j == 0)
	cprintf(ch, "You are very confused.\r\n");
    if (j == level >> 1)
	cprintf(ch, "No such object.\r\n");
}

void spell_poison(char level, struct char_data *ch, struct char_data *victim,
		  struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim && !obj)
	return;

    if (victim) {
	if (!CheckKill(ch, victim))
	    return;

	if (IS_NOT_SET(ch->specials.act, ACT_DEADLY)) {
	    if (!ImpSaveSpell(victim, SAVING_PARA, 0)) {
		af.type = SPELL_POISON;
		af.duration = 6;
		af.modifier = -2;
		af.location = APPLY_STR;
		af.bitvector = AFF_POISON;
		affect_join(victim, &af, FALSE, FALSE);
		cprintf(victim, "You feel very sick.\r\n");
		if (!victim->specials.fighting)
		    set_fighting(victim, ch);
	    } else {
		if (!victim->specials.fighting)
		    set_fighting(victim, ch);
		return;
	    }
	} else {
	    if (!ImpSaveSpell(victim, SAVING_PARA, 0)) {
		act("Deadly poison fills your veins.", TRUE, ch, 0, 0, TO_CHAR);
		damage(ch, victim, MAX(10, GET_HIT(victim) * 2), SPELL_POISON);
		if (!victim->specials.fighting)
		    set_fighting(victim, ch);
	    } else {
		if (!victim->specials.fighting)
		    set_fighting(victim, ch);
		return;
	    }
	}
    } else {						       /* Object poison */
	if ((obj->obj_flags.type_flag == ITEM_DRINKCON)
	    || (obj->obj_flags.type_flag == ITEM_FOOD)) {
	    obj->obj_flags.value[3] = 1;
	}
    }
}

void spell_protection_from_evil(char level, struct char_data *ch, struct char_data *victim,
				struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;

    if (!affected_by_spell(victim, SPELL_PROTECT_FROM_EVIL)) {
	af.type = SPELL_PROTECT_FROM_EVIL;
	af.duration = 1 + (level / 2);
	af.modifier = 0;
	af.location = APPLY_NONE;
	af.bitvector = AFF_PROTECT_EVIL;
	affect_to_char(victim, &af);
	cprintf(victim, "You have a righteous feeling!\r\n");
    }
}

void spell_remove_curse(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(ch && (victim || obj)))
	return;

    if (DEBUG)
	log_info("spell_remove_curse");
    if (obj) {
	if (IS_SET(obj->obj_flags.extra_flags, ITEM_NODROP)) {
	    act("$p briefly glows blue.", TRUE, ch, obj, 0, TO_CHAR);
	    REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_NODROP);
	}
    } else {						       /* Then it is a PC | NPC */
	if (affected_by_spell(victim, SPELL_CURSE)) {
	    act("$n briefly glows red, then blue.", FALSE, victim, 0, 0, TO_ROOM);
	    act("You feel better.", FALSE, victim, 0, 0, TO_CHAR);
	    affect_from_char(victim, SPELL_CURSE);
	}
    }
}

void spell_remove_poison(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(ch && (victim || obj)))
	return;

    if (victim) {
	if (affected_by_spell(victim, SPELL_POISON)) {
	    affect_from_char(victim, SPELL_POISON);
	    act("A warm feeling runs through your body.", FALSE, victim, 0, 0, TO_CHAR);
	    act("$N looks better.", FALSE, ch, 0, victim, TO_ROOM);
	}
    } else {
	if ((obj->obj_flags.type_flag == ITEM_DRINKCON)
	    || (obj->obj_flags.type_flag == ITEM_FOOD)) {
	    obj->obj_flags.value[3] = 0;
	    act("The $p steams briefly.", FALSE, ch, obj, 0, TO_CHAR);
	}
    }
}

void spell_fireshield(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!affected_by_spell(victim, SPELL_FIRESHIELD)) {
	act("$n is surrounded by a glowing red aura.", TRUE, victim, 0, 0, TO_ROOM);
	act("You start glowing red.", TRUE, victim, 0, 0, TO_CHAR);

	af.type = SPELL_FIRESHIELD;
	af.duration = 2 + level;
	af.modifier = 0;
	af.location = APPLY_NONE;
	af.bitvector = AFF_FIRESHIELD;
	affect_to_char(victim, &af);
    }
}

void spell_sanctuary(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!affected_by_spell(victim, SPELL_SANCTUARY)) {
	act("$n is surrounded by a white aura.", TRUE, victim, 0, 0, TO_ROOM);
	act("You start glowing.", TRUE, victim, 0, 0, TO_CHAR);

	af.type = SPELL_SANCTUARY;
	af.duration = (level / 2);
	af.modifier = 0;
	af.location = APPLY_NONE;
	af.bitvector = AFF_SANCTUARY;
	affect_to_char(victim, &af);
    }
}

void spell_sleep(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;

    if (!CheckKill(ch, victim))
	return;

    if (IsImmune(victim, IMM_SLEEP)) {
	FailSleep(victim, ch);
	return;
    }
    if (IsResist(victim, IMM_SLEEP)) {
	if (saves_spell(victim, SAVING_SPELL)) {
	    FailSleep(victim, ch);
	    return;
	}
	if (saves_spell(victim, SAVING_SPELL)) {
	    FailSleep(victim, ch);
	    return;
	}
    } else if (!IsSusc(victim, IMM_SLEEP)) {
	if (saves_spell(victim, SAVING_SPELL)) {
	    FailSleep(victim, ch);
	    return;
	}
    }
    af.type = SPELL_SLEEP;
    af.duration = 1;
    af.modifier = 0;
    af.location = APPLY_NONE;
    af.bitvector = AFF_SLEEP;
    affect_join(victim, &af, FALSE, FALSE);

    if (GET_POS(victim) > POSITION_SLEEPING) {
	act("You feel very sleepy .....", FALSE, victim, 0, 0, TO_CHAR);
	act("$n goes to sleep.", TRUE, victim, 0, 0, TO_ROOM);
	GET_POS(victim) = POSITION_SLEEPING;
    }
}

void spell_strength(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;

    if (!affected_by_spell(victim, SPELL_STRENGTH)) {
	act("You feel stronger.", FALSE, victim, 0, 0, TO_CHAR);
	act("$n seems stronger!\r\n", FALSE, victim, 0, 0, TO_ROOM);
	af.type = SPELL_STRENGTH;
	af.duration = 1 + MIN((level / 4), 10) - HowManyClasses(ch);
	if (af.duration < 1)
	    af.duration = 1;

	if (IS_NPC(victim))
	    af.modifier = number(1, 6);
	else {
	    if (HasClass(victim, CLASS_WARRIOR) || HasClass(victim, CLASS_RANGER))
		af.modifier = number(1, 4);
	    else if (HasClass(victim, CLASS_CLERIC) ||
		     HasClass(victim, CLASS_THIEF) || HasClass(victim, CLASS_DRUID))
		af.modifier = number(1, 3);
	    else
		af.modifier = number(1, 2);
	}
	af.location = APPLY_STR;
	af.bitvector = 0;
	affect_to_char(victim, &af);
    } else {
	act("Nothing seems to happen.", FALSE, ch, 0, 0, TO_CHAR);
    }
}

void spell_ventriloquate(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    /*
     * Not possible!! No argument! 
     */
}

void spell_word_of_recall(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     location = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;
    if (IS_NPC(victim))
	return;

    location = GET_HOME(ch);				       /* Shouldn't this be victim? */

    if (!real_roomp(location)) {
	cprintf(victim, "You are completely lost.\r\n");
	return;
    }
    /*
     * a location has been found. 
     */

    act("$n disappears.", TRUE, victim, 0, 0, TO_ROOM);
    char_from_room(victim);
    char_to_room(victim, location);
    act("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM);
    do_look(victim, "", 15);
}

void spell_summon(char level, struct char_data *ch, struct char_data *victim,
		  struct obj_data *obj)
{
    short int                               target = 0;
    struct char_data                       *tmp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(ch && victim))
	return;

    if (IS_NPC(victim) && saves_spell(victim, SAVING_SPELL)) {
	cprintf(ch, "You failed.\r\n");
	return;
    }
    if (IS_SET(victim->specials.new_act, NEW_PLR_SUMMON)) {
	cprintf(ch, "Sorry, that does not want to be summoned.\r\n");
	return;
    }
    if (IS_SET(real_roomp(victim->in_room)->room_flags, NO_SUM)) {
	cprintf(ch, "You cannot penetrate the magical defenses of that area.\r\n");
	return;
    }
    tmp = victim;
    act("$n disappears suddenly.", TRUE, tmp, 0, 0, TO_ROOM);
    target = ch->in_room;

    if (MOUNTED(tmp)) {
	char_from_room(tmp);
	char_from_room(MOUNTED(tmp));
	char_to_room(tmp, target);
	char_to_room(MOUNTED(tmp), target);
	act("$n and a mount slowly fade out of existence.", FALSE, tmp, 0, 0, TO_ROOM);
	act("$n slowly fades into existence.", FALSE, tmp, 0, 0, TO_ROOM);
    } else if (RIDDEN(tmp)) {
	char_from_room(RIDDEN(tmp));
	char_from_room(tmp);
	char_to_room(RIDDEN(tmp), target);
	char_to_room(tmp, target);
	act("$n and a rider slowly fade out of existence.", FALSE, ch, 0, 0, TO_ROOM);
	act("$n slowly fades into existence.", FALSE, ch, 0, 0, TO_ROOM);
    } else {
	char_from_room(tmp);
	char_to_room(tmp, target);
	act("$n slowly fades out of existence.", FALSE, ch, 0, 0, TO_ROOM);
	act("$n slowly fades in to existence.", FALSE, ch, 0, 0, TO_ROOM);
    }

    act("$n arrives suddenly.", TRUE, tmp, 0, 0, TO_ROOM);
    act("$n has summoned you!", FALSE, ch, 0, tmp, TO_VICT);

    if (IS_PC(victim))
	do_look(tmp, "", 15);
    if (IS_NPC(victim)) {
	if (MOUNTED(victim))
	    if (IS_NPC(MOUNTED(victim)))
		set_fighting(victim, ch);

	if (RIDDEN(victim))
	    if (IS_NPC(RIDDEN(victim)))
		set_fighting(victim, ch);
    }
}

void spell_charm_monster(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(ch && victim))
	return;

    if (victim == ch) {
	cprintf(ch, "You like yourself even better!\r\n");
	return;
    }
    if (!CheckKill(ch, victim))
	return;

    if (!IS_AFFECTED(victim, AFF_CHARM) && !IS_AFFECTED(ch, AFF_CHARM)) {
	if (circle_follow(victim, ch)) {
	    cprintf(ch, "Sorry, following in circles can not be allowed.\r\n");
	    return;
	}
	if (IsPerson(victim)) {
	    cprintf(ch, "How insulting!  That is a person, not a beast!\r\n");
	    return;
	}
	if (IsImmune(victim, IMM_CHARM)) {
	    FailCharm(victim, ch);
	    return;
	}
	if (IsResist(victim, IMM_CHARM)) {
	    if (saves_spell(victim, SAVING_PARA)) {
		FailCharm(victim, ch);
		return;
	    }
	    if (saves_spell(victim, SAVING_PARA)) {
		FailCharm(victim, ch);
		return;
	    }
	} else {
	    if (!IsSusc(victim, IMM_CHARM)) {
		if (saves_spell(victim, SAVING_PARA)) {
		    FailCharm(victim, ch);
		    return;
		}
	    }
	}

	if (victim->master)
	    stop_follower(victim);

	add_follower(victim, ch);

	af.type = SPELL_CHARM_PERSON;

	if (GET_INT(victim))
	    af.duration = 20 - GET_INT(victim);
	else
	    af.duration = 14;

	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(victim, &af);

	cprintf(ch, "They are now charmed.....\r\n");
	act("Isn't $n just such a nice fellow?", FALSE, ch, 0, victim, TO_VICT);
    }
}

void spell_sense_life(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;

    if (!affected_by_spell(victim, SPELL_SENSE_LIFE)) {
	cprintf(ch, "Your feel your awareness improve.\r\n");

	af.type = SPELL_SENSE_LIFE;
	af.duration = 1 + (level / 2);
	af.modifier = 0;
	af.location = APPLY_NONE;
	af.bitvector = AFF_SENSE_LIFE;
	affect_to_char(victim, &af);
    }
}

/* ***************************************************************************
 *                     Not cast-able spells                                  *
 * ************************************************************************* */

void spell_identify(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    char                                    buf[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    char                                    buf2[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    int                                     i = 0;
    int                                     found = FALSE;
    int                                     val_index = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(ch && (obj || victim)))
	return;

    if (obj) {
	cprintf(ch, "You feel informed:\r\n");
	sprintf(buf, "Object '%s', Item type: ", obj->name);
	sprinttype(GET_ITEM_TYPE(obj), item_types, buf2);
	strcat(buf, buf2);
	strcat(buf, "\r\n");
	cprintf(ch, "%s", buf);

	if (obj->obj_flags.bitvector) {
	    cprintf(ch, "Item aids in abilities:  ");
	    sprintbit(obj->obj_flags.bitvector, affected_bits, buf);
	    strcat(buf, "\r\n");
	    cprintf(ch, "%s", buf);
	}
	cprintf(ch, "Item is: ");
	sprintbit(obj->obj_flags.extra_flags, extra_bits, buf);
	strcat(buf, "\r\n");
	cprintf(ch, "%s", buf);

	cprintf(ch, "Weight: %d, Value: %d\r\n", obj->obj_flags.weight, obj->obj_flags.cost);

	switch (GET_ITEM_TYPE(obj)) {
	    case ITEM_SCROLL:
	    case ITEM_POTION:
		cprintf(ch, "Level %d spells of:\r\n", obj->obj_flags.value[0]);
		for (val_index = 1; val_index < 4; val_index++)
		    if (obj->obj_flags.value[val_index] > 0
			&& obj->obj_flags.value[val_index] < MAX_SKILLS) {
			strcat(buf, spell_info[obj->obj_flags.value[val_index]].name);
			strcat(buf, "\r\n");
			cprintf(ch, "%s", buf);
		    }
		break;

	    case ITEM_WAND:
	    case ITEM_STAFF:
		cprintf(ch, "Has %d chages, with %d charges left.\r\n",
			obj->obj_flags.value[1], obj->obj_flags.value[2]);

		cprintf(ch, "Level %d spell of:\r\n", obj->obj_flags.value[0]);

		if (obj->obj_flags.value[3] > 0 && obj->obj_flags.value[3] < MAX_SKILLS) {
		    strcat(buf, spell_info[obj->obj_flags.value[3]].name);
		    strcat(buf, "\r\n");
		    cprintf(ch, "%s", buf);
		}
		break;

	    case ITEM_WEAPON:
		cprintf(ch, "Damage Dice is '%dD%d'\r\n",
			obj->obj_flags.value[1], obj->obj_flags.value[2]);
		break;

	    case ITEM_ARMOR:
		cprintf(ch, "AC-apply is %d\r\n", obj->obj_flags.value[0]);
		break;
	}

	found = FALSE;

	for (i = 0; i < MAX_OBJ_AFFECT; i++) {
	    if ((obj->affected[i].location != APPLY_NONE) && (obj->affected[i].modifier != 0)) {
		if (!found) {
		    cprintf(ch, "Can affect you as :\r\n");
		    found = TRUE;
		}
		sprinttype(obj->affected[i].location, apply_types, buf2);
		cprintf(ch, "    Affects : %s By %d\r\n", buf2, obj->affected[i].modifier);
	    }
	}
    }
}

/* ***************************************************************************
 *                     NPC spells..                                          *
 * ************************************************************************* */

void spell_fire_breath(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     hpch = 0;
    struct obj_data                        *burn = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    hpch = GET_MAX_HIT(ch);
    hpch *= level;
    hpch /= GetMaxLevel(ch);
    if (hpch < 10)
	hpch = 10;

    dam = hpch;

    if (saves_spell(victim, SAVING_BREATH))
	dam >>= 1;

    damage(ch, victim, dam, SPELL_FIRE_BREATH);

    /*
     * And now for the damage on inventory 
     */

    for (burn = victim->carrying;
	 burn && (burn->obj_flags.type_flag != ITEM_SCROLL) &&
	 (burn->obj_flags.type_flag != ITEM_WAND) &&
	 (burn->obj_flags.type_flag != ITEM_STAFF) &&
	 (burn->obj_flags.type_flag != ITEM_BOAT); burn = burn->next_content) {
	if (!saves_spell(victim, SAVING_BREATH)) {
	    if (burn) {
		act("$o burns", 0, victim, burn, 0, TO_CHAR);
		extract_obj(burn);
	    }
	}
    }
}

void spell_frost_breath(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     hpch = 0;
    struct obj_data                        *frozen = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    hpch = GET_MAX_HIT(ch);
    hpch *= level;
    hpch /= GetMaxLevel(ch);
    if (hpch < 10)
	hpch = 10;

    dam = hpch;

    if (saves_spell(victim, SAVING_BREATH))
	dam >>= 1;

    damage(ch, victim, dam, SPELL_FROST_BREATH);

    /*
     * And now for the damage on inventory 
     */

    for (frozen = victim->carrying;
	 frozen && (frozen->obj_flags.type_flag != ITEM_DRINKCON) &&
	 (frozen->obj_flags.type_flag != ITEM_POTION); frozen = frozen->next_content) {
	if (!saves_spell(victim, SAVING_BREATH)) {
	    if (frozen) {
		act("$o shatters.", 0, victim, frozen, 0, TO_CHAR);
		extract_obj(frozen);
	    }
	}
    }
}

void spell_acid_breath(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     hpch = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    hpch = GET_MAX_HIT(ch);
    hpch *= level;
    hpch /= GetMaxLevel(ch);
    if (hpch < 10)
	hpch = 10;

    dam = hpch;

    if (saves_spell(victim, SAVING_BREATH))
	dam >>= 1;

    damage(ch, victim, dam, SPELL_ACID_BREATH);

}

void spell_gas_breath(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     hpch = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    hpch = GET_MAX_HIT(ch);
    hpch *= level;
    hpch /= GetMaxLevel(ch);
    if (hpch < 10)
	hpch = 10;

    dam = hpch;

    if (saves_spell(victim, SAVING_BREATH))
	dam >>= 1;

    damage(ch, victim, dam, SPELL_GAS_BREATH);

}

void spell_lightning_breath(char level, struct char_data *ch, struct char_data *victim,
			    struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     hpch = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    hpch = GET_MAX_HIT(ch);
    hpch *= level;
    hpch /= GetMaxLevel(ch);
    if (hpch < 10)
	hpch = 10;

    dam = hpch;

    if (saves_spell(victim, SAVING_BREATH))
	dam >>= 1;

    damage(ch, victim, dam, SPELL_LIGHTNING_BREATH);

}

/*
 * file: magic2.c , Implementation of (new)spells.        Part of DIKUMUD
 * Usage : The actual effect of magic.
 */

/*
 * cleric spells
 */

/*
 **   requires the sacrifice of 150k coins, victim loses a con point, and
 **   caster is knocked down to 1 hp, 1 mp, 1 mana, and sits for a LONG
 **   time (if a pc)
 */

void spell_resurrection(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct char_file_u                      st;
    struct affected_type                    af;
    struct obj_data                        *obj_object = NULL;
    struct obj_data                        *next_obj = NULL;
    FILE                                   *fl = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!obj)
	return;

    if (IS_CORPSE(obj)) {
	if (obj->char_vnum) {				       /* corpse is a npc */
	    victim = read_mobile(obj->char_vnum, VIRTUAL);
	    char_to_room(victim, ch->in_room);
	    GET_GOLD(victim) = 0;
	    GET_EXP(victim) = 0;
	    GET_HIT(victim) = 1;
	    GET_POS(victim) = POSITION_STUNNED;

	    act("With mystic power, $n resurrects a corpse.", TRUE, ch, 0, 0, TO_ROOM);
	    act("$N slowly rises from the ground.", FALSE, ch, 0, victim, TO_ROOM);

	    /*
	     * should be charmed and follower ch
	     */

	    if (IsImmune(victim, IMM_CHARM) || IsResist(victim, IMM_CHARM)) {
		act("$n says 'Thank you'", FALSE, ch, 0, victim, TO_ROOM);
	    } else {
		af.type = SPELL_CHARM_PERSON;
		af.duration = 36;
		af.modifier = 0;
		af.location = 0;
		af.bitvector = AFF_CHARM;

		affect_to_char(victim, &af);

		add_follower(victim, ch);
	    }

	    IS_CARRYING_W(victim) = 0;
	    IS_CARRYING_N(victim) = 0;

	    /*
	     * take all from corpse, and give to person
	     */

	    for (obj_object = obj->contains; obj_object; obj_object = next_obj) {
		next_obj = obj_object->next_content;
		obj_from_obj(obj_object);
		obj_to_char(obj_object, victim);
	    }

	    /*
	     * get rid of corpse
	     */
	    extract_obj(obj);

	} else {					       /* corpse is a pc */

	    if (GET_GOLD(ch) < 100000) {
		cprintf(ch, "The gods are not happy with your sacrifice.\r\n");
		return;
	    } else {
		GET_GOLD(ch) -= 100000;
	    }

	    fl = fopen(PLAYER_FILE, "r+");
	    if (!fl) {
		log_fatal("player file");
		proper_exit(MUD_HALT);
	    }
	    fseek(fl, obj->char_f_pos * sizeof(struct char_file_u), 0);
	    fread(&st, sizeof(struct char_file_u), 1, fl);

	    /*
	     **   this is a serious kludge, and must be changed before multiple
	     **   languages can be implemented
	     */
	    if (!st.talks[2] && st.abilities.con > 3) {
		st.points.exp *= 2;
		st.talks[2] = TRUE;
		st.abilities.con -= 1;
		act("A clear bell rings throughout the heavens", TRUE, ch, 0, 0, TO_CHAR);
		act("A ghostly spirit smiles, and says 'Thank you'", TRUE, ch, 0, 0, TO_CHAR);
		act("A clear bell rings throughout the heavens", TRUE, ch, 0, 0, TO_ROOM);
		act("A ghostly spirit smiles, and says 'Thank you'", TRUE, ch, 0, 0, TO_ROOM);
		act("$p dissappears in the blink of an eye.", TRUE, ch, obj, 0, TO_ROOM);
		act("$p dissappears in the blink of an eye.", TRUE, ch, obj, 0, TO_ROOM);
		GET_MANA(ch) = 1;
		GET_MOVE(ch) = 1;
		GET_HIT(ch) = 1;
		GET_POS(ch) = POSITION_STUNNED;
		act("$n collapses from the effort!", TRUE, ch, 0, 0, TO_ROOM);
		cprintf(ch, "You collapse from the effort\r\n");
		fseek(fl, obj->char_f_pos * sizeof(struct char_file_u), 0);
		fwrite(&st, sizeof(struct char_file_u), 1, fl);

		ObjFromCorpse(obj);

	    } else {
		cprintf(ch, "The body does not have the strength to be recreated.\r\n");
	    }
	    FCLOSE(fl);
	}
    }
}

void spell_cause_light(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;

    if (HowManyClasses(ch) == 1)
	dam = dice(2, 4) + 1;
    else
	dam = dice(1, 8);

    if (IS_REALLY_HOLY(ch))
	dam -= dice(1, 3);
    else if (IS_HOLY(ch))
	dam -= dice(1, 2);
    else if (IS_VILE(ch))
	dam += dice(1, 2);
    else if (IS_REALLY_VILE(ch))
	dam += dice(1, 3);

    if (dam < 1)
	dam = 1;

    damage(ch, victim, dam, SPELL_CAUSE_LIGHT);
}

void spell_cause_critical(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;
    if (HowManyClasses(ch) == 1)
	dam = dice(4, 6) + 3;
    else
	dam = dice(3, 8);

    if (IS_REALLY_HOLY(ch))
	dam -= dice(1, 6);
    else if (IS_HOLY(ch))
	dam -= dice(1, 3);
    else if (IS_VILE(ch))
	dam += dice(1, 3);
    else if (IS_REALLY_VILE(ch))
	dam += dice(1, 6);

    if (dam < 1)
	dam = 1;

    damage(ch, victim, dam, SPELL_CAUSE_CRITICAL);
}

void spell_cause_serious(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;
    if (HowManyClasses(ch) == 1)
	dam = dice(4, 4) + 2;
    else
	dam = dice(2, 8);

    if (IS_REALLY_HOLY(ch))
	dam -= dice(1, 4);
    else if (IS_HOLY(ch))
	dam -= dice(1, 2);
    else if (IS_VILE(ch))
	dam += dice(1, 2);
    else if (IS_REALLY_VILE(ch))
	dam += dice(1, 4);

    if (dam < 1)
	dam = 1;

    damage(ch, victim, dam, SPELL_CAUSE_SERIOUS);

}

void spell_cure_serious(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (HowManyClasses(ch) == 1)
	dam = dice(4, 4) + 2;
    else
	dam = dice(2, 8);

    if (IS_REALLY_HOLY(ch))
	dam += dice(1, 4);
    else if (IS_HOLY(ch))
	dam += dice(1, 2);
    else if (IS_VILE(ch))
	dam -= dice(1, 2);
    else if (IS_REALLY_VILE(ch))
	dam -= dice(1, 4);

    if (dam < 1)
	dam = 1;

    if ((dam + GET_HIT(victim)) > hit_limit(victim))
	GET_HIT(victim) = hit_limit(victim);
    else
	GET_HIT(victim) += dam;

    cprintf(victim, "You feel better!\r\n");
    update_pos(victim);
    if (ch)
	cprintf(ch, "%s %s.\r\n", NAME(victim), pain_level(victim));
}

void spell_mana(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    dam = dice(level, 4);
    dam = MAX(dam, level * 2);

    if (GET_MANA(ch) + dam > GET_MAX_MANA(ch))
	GET_MANA(ch) = GET_MAX_MANA(ch);
    else
	GET_MANA(ch) += dam;

}

void spell_second_wind(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    dam = dice(level, 8) + level;

    if ((dam + GET_MOVE(victim)) > move_limit(victim))
	GET_MOVE(victim) = move_limit(victim);
    else
	GET_MOVE(victim) += dam;

    cprintf(victim, "You feel less tired\r\n");

}

void spell_flamestrike(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;
    dam = dice((8 - HowManyClasses(ch)), 8);

    if (saves_spell(victim, SAVING_SPELL))
	dam >>= 1;

    cprintf(ch, "You summon forth a pillar of flame....\r\n");
    damage(ch, victim, dam, SPELL_FLAMESTRIKE);
}

void spell_dispel_good(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;

    if (IsExtraPlanar(victim)) {
	if (IS_GOOD(ch)) {
	    victim = ch;
	} else if (IS_EVIL(victim)) {
	    act("Evil protects $N.", FALSE, ch, 0, victim, TO_CHAR);
	    return;
	}
	if (!saves_spell(victim, SAVING_SPELL)) {
	    act("$n forces $N from this plane.", TRUE, ch, 0, victim, TO_NOTVICT);
	    act("You force $N from this plane.", TRUE, ch, 0, victim, TO_CHAR);
	    act("$n forces you from this plane.", TRUE, ch, 0, victim, TO_VICT);
	    gain_exp(ch, MIN(GET_EXP(victim) / 2, 50000));
	    extract_char(victim);
	}
    } else {
	act("$N laughs at you.", TRUE, ch, 0, victim, TO_CHAR);
	act("$N laughs at $n.", TRUE, ch, 0, victim, TO_NOTVICT);
	act("You laugh at $n.", TRUE, ch, 0, victim, TO_VICT);
    }
}

void spell_turn(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    int                                     diff = 0;
    int                                     i = 0;
    int                                     flag = 0;
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IsUndead(victim)) {
	diff = level - GetTotLevel(victim);
	if (diff <= 0) {
	    act("You are powerless to affect $N", TRUE, ch, 0, victim, TO_CHAR);
	    return;
	} else {
	    for (i = 1; i <= diff; i++) {
		if (!saves_spell(victim, SAVING_SPELL)) {
		    if (!saves_spell(victim, SAVING_SPELL)) {
			if (IS_GOOD(ch)) {
			    /*
			     * caster is good....kill the mob/player 
			     */
			    act("$N falls to the ground and convulses uncontrollably.",
				TRUE, ch, 0, victim, TO_NOTVICT);
			    act("You fall to the ground, mortally wounded!", TRUE, ch, 0,
				victim, TO_VICT);
			    act("$N falls to the ground as you devour $E life force!", TRUE, ch,
				0, victim, TO_CHAR);
			    damage(ch, victim, (GET_HIT(victim) + 1), SPELL_FLAMESTRIKE);
			    update_pos(victim);
			    return;
			} else if (IS_VILE(ch)) {
			    if (!IsImmune(victim, IMM_CHARM)) {
				/*
				 * caster is evil...enslave the mob/player 
				 */
				act("$N shivers for a moment, then stares vacantly at $n.",
				    TRUE, ch, 0, victim, TO_NOTVICT);
				act("You shiver as $n invades your mind and possesses you.",
				    TRUE, ch, 0, victim, TO_VICT);
				act("$N shivers as you utter a prayer and take possession of $n's mind.", TRUE, ch, 0, victim, TO_CHAR);
				if (victim->master)
				    stop_follower(victim);
				if (circle_follow(victim, ch)) {
				    affect_from_char(ch, SPELL_CHARM_PERSON);
				    stop_follower(ch);
				}
				add_follower(victim, ch);
				af.type = SPELL_CHARM_PERSON;
				if (GET_INT(victim))
				    af.duration = 20 - GET_INT(victim);
				else
				    af.duration = 12;
				af.modifier = 0;
				af.location = 0;
				af.bitvector = AFF_CHARM;
				affect_to_char(victim, &af);
				REMOVE_BIT(victim->specials.act, ACT_AGGRESSIVE);
				return;
			    }
			} else {
			    break;
			}
		    } else {
			act("$n forces $N from this room.", TRUE, ch, 0, victim, TO_NOTVICT);
			act("You force $N from this room.", TRUE, ch, 0, victim, TO_CHAR);
			act("$n forces you from this room.", TRUE, ch, 0, victim, TO_VICT);
			do_flee(victim, "", 0);
			flag = 1;
			break;
		    }
		}
	    }
	    if (!flag) {
		act("You laugh at $n.", TRUE, ch, 0, victim, TO_VICT);
		act("$N laughs at $n.", TRUE, ch, 0, victim, TO_NOTVICT);
		act("$N laughs at you.", TRUE, ch, 0, victim, TO_CHAR);
	    }
	}
    } else {
	act("$n just tried to turn you, what a moron!", TRUE, ch, 0, victim, TO_VICT);
	act("$N thinks $n is really strange.", TRUE, ch, 0, victim, TO_NOTVICT);
	act("Um... $N isn't undead...", TRUE, ch, 0, victim, TO_CHAR);
    }
}

void spell_remove_paralysis(char level, struct char_data *ch, struct char_data *victim,
			    struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(victim, SPELL_PARALYSIS)) {
	affect_from_char(victim, SPELL_PARALYSIS);
	act("A warm feeling runs through your body.", FALSE, victim, 0, 0, TO_CHAR);
	act("$N looks better.", FALSE, ch, 0, victim, TO_ROOM);
    }
}

void spell_holy_word(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_unholy_word(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_succor(char level, struct char_data *ch, struct char_data *victim,
		  struct obj_data *obj)
{
    struct obj_data                        *o = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    o = read_object(1901, VIRTUAL);
    obj_to_char(o, ch);
    act("$n waves $s hand, and creates $p", TRUE, ch, o, 0, TO_ROOM);
    act("You wave your hand and create $p.", TRUE, ch, o, 0, TO_CHAR);
}

void spell_detect_charm(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_true_seeing(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!IS_AFFECTED(victim, AFF_TRUE_SIGHT)) {
	if (ch != victim) {
	    cprintf(victim, "Your eyes glow silver for a moment.\r\n");
	    act("$n's eyes take on a silvery hue.\r\n", FALSE, victim, 0, 0, TO_ROOM);
	} else {
	    cprintf(ch, "Your eyes glow silver.\r\n");
	    act("$n's eyes glow silver.\r\n", FALSE, ch, 0, 0, TO_ROOM);
	}

	af.type = SPELL_TRUE_SIGHT;
	af.duration = level / 2;
	af.modifier = 0;
	af.location = APPLY_NONE;
	af.bitvector = AFF_TRUE_SIGHT;
	affect_to_char(victim, &af);
    } else {
	cprintf(ch, "Nothing seems to happen\r\n");
    }
}

/*
 * magic user spells
 */

void spell_poly_self(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
    /*
     * victim is a prototype mob 
     */

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!ch->desc || ch->desc->snoop.snoop_by || ch->desc->snoop.snooping) {
	cprintf(ch, "Godly interference prevents the spell from working.");
	return;
    }
    char_to_room(victim, ch->in_room);

    act("$n's flesh melts and flows into the shape of $N", TRUE, ch, 0, victim, TO_ROOM);
    act("Your flesh melts and flows into the shape of $N", TRUE, ch, 0, victim, TO_CHAR);

    char_from_room(ch);
    char_to_room(ch, 3);

    ch->desc->character = victim;
    ch->desc->original = ch;

    victim->desc = ch->desc;
    ch->desc = 0;

    SET_BIT(victim->specials.act, ACT_POLYSELF);
    GET_EXP(victim) = 10;
}

void spell_minor_create(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(obj && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    act("$n claps $s hands together.", TRUE, ch, 0, 0, TO_ROOM);
    act("You clap your hands together.", TRUE, ch, 0, 0, TO_CHAR);
    act("In a flash of light, $p appears.", TRUE, ch, obj, 0, TO_ROOM);
    act("In a flash of light, $p appears.", TRUE, ch, obj, 0, TO_CHAR);
    obj_to_room(obj, ch->in_room);

}

void spell_stone_skin(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!affected_by_spell(ch, SPELL_STONE_SKIN)) {
	act("$n's skin turns grey and granite-like.", TRUE, ch, 0, 0, TO_ROOM);
	act("Your skin turns to a stone-like substance.", TRUE, ch, 0, 0, TO_CHAR);

	af.type = SPELL_STONE_SKIN;
	af.duration = (level / 4 - (dice(HowManyClasses(ch), 3)));
	if (af.duration < 1)
	    af.duration = 1;

	af.modifier = -30;
	af.location = APPLY_AC;
	af.bitvector = 0;
	affect_to_char(ch, &af);

	/*
	 * resistance to piercing weapons 
	 */

	af.type = SPELL_STONE_SKIN;
	af.duration = (level / 8 - (dice(HowManyClasses(ch), 3)));
	if (af.duration < 1)
	    af.duration = 1;
	af.modifier = 32;
	af.location = APPLY_IMMUNE;
	af.bitvector = 0;
	affect_to_char(ch, &af);
    } else
	cprintf(ch, "The spell fizzles...\r\n");
}

void spell_infravision(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!IS_AFFECTED(victim, AFF_INFRAVISION)) {
	if (ch != victim) {
	    cprintf(victim, "Your eyes glow red.\r\n");
	    act("$n's eyes glow red.\r\n", FALSE, victim, 0, 0, TO_ROOM);
	} else {
	    cprintf(ch, "Your eyes glow red.\r\n");
	    act("$n's eyes glow red.\r\n", FALSE, ch, 0, 0, TO_ROOM);
	}

	af.type = SPELL_INFRAVISION;
	af.duration = level;
	af.modifier = 0;
	af.location = APPLY_NONE;
	af.bitvector = AFF_INFRAVISION;
	affect_to_char(victim, &af);
    }
}

void spell_shield(char level, struct char_data *ch, struct char_data *victim,
		  struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!affected_by_spell(victim, SPELL_SHIELD)) {
	act("$N is surrounded by a strong force shield.", TRUE, ch, 0, victim, TO_NOTVICT);
	if (ch != victim) {
	    act("$N is surrounded by a strong force shield.", TRUE, ch, 0, victim, TO_CHAR);
	    act("You are surrounded by a strong force shield.", TRUE, ch, 0, victim, TO_VICT);
	} else {
	    act("You are surrounded by a strong force shield.", TRUE, ch, 0, victim, TO_VICT);
	}

	af.type = SPELL_SHIELD;
	af.duration = level;
	af.modifier = -10;
	af.location = APPLY_AC;
	af.bitvector = 0;
	affect_to_char(victim, &af);
    } else
	cprintf(ch, "The spell fizzles....\r\n");
}

void spell_weakness(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    struct affected_type                    af;
    float                                   modifier = 0.0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(victim && ch))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;

    if (!affected_by_spell(victim, SPELL_WEAKNESS))
	if (!saves_spell(victim, SAVING_SPELL)) {
	    modifier = (77.0 - level) / 100.0;
	    act("You feel weaker.", FALSE, victim, 0, 0, TO_VICT);
	    act("$n seems weaker.", FALSE, victim, 0, 0, TO_ROOM);

	    af.type = SPELL_WEAKNESS;
	    af.duration = (int)level / 2;
	    af.modifier = (int)0 - (victim->abilities.str * modifier);
	    if (victim->abilities.str_add)
		af.modifier -= 2;
	    af.location = APPLY_STR;
	    af.bitvector = 0;

	    affect_to_char(victim, &af);
	}
}

void spell_invis_group(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct char_data                       *tmp_victim = NULL;
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    for (tmp_victim = real_roomp(ch->in_room)->people; tmp_victim;
	 tmp_victim = tmp_victim->next_in_room) {
	if ((ch->in_room == tmp_victim->in_room) && (ch != tmp_victim))
	    if (in_group(ch, tmp_victim)) {
		if (!affected_by_spell(tmp_victim, SPELL_INVISIBLE)) {

		    act("$n slowly fades out of existence.", TRUE, tmp_victim, 0, 0, TO_ROOM);
		    cprintf(tmp_victim, "You vanish.\r\n");

		    af.type = SPELL_INVISIBLE;
		    af.duration = level / 2;
		    af.modifier = -40;
		    af.location = APPLY_AC;
		    af.bitvector = AFF_INVISIBLE;
		    affect_to_char(tmp_victim, &af);
		}
	    }
    }
}

void spell_acid_blast(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     high_die = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim || !ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;
    if (!CheckKill(ch, victim))
	return;

    switch (HowManyClasses(ch)) {
	case 1:
	    high_die = 5 + ((level / 7) - 1);
	    break;
	case 2:
	    high_die = 5 + ((level / 8) - 1);
	    break;
	case 3:
	    high_die = 5 + ((level / 9) - 1);
	    break;
	case 4:
	    high_die = 5 + ((level / 10) - 1);
	    break;
	default:
	    high_die = 5 + ((level / 11) - 1);
	    break;
    }

    dam = dice(high_die, 6);

    if (saves_spell(victim, SAVING_SPELL))
	dam >>= 1;
    damage(ch, victim, dam, SPELL_ACID_BLAST);
}

void spell_cone_of_cold(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     high_die = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    switch (HowManyClasses(ch)) {
	case 1:
	    high_die = 5 + ((level / 5) - 1);
	    break;
	case 2:
	    high_die = 4 + ((level / 6) - 1);
	    break;
	case 3:
	    high_die = 4 + ((level / 7) - 1);
	    break;
	case 4:
	    high_die = 4 + ((level / 8) - 1);
	    break;
	default:
	    high_die = 4 + ((level / 9) - 1);
	    break;
    }

    dam = dice(high_die, 3) + 1;

    cprintf(ch, "A cone of freezing air fans out before you\r\n");
    act("$n sends a cone of ice shooting from their fingertips!\r\n", FALSE, ch, 0, 0, TO_ROOM);
    AreaEffectSpell(ch, dam, SPELL_CONE_OF_COLD, 0, NULL);
}

void spell_ice_storm(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    dam = dice(3, 20);

    cprintf(ch, "You conjure a huge cloud of ice crystals...they hover just above\r\n");
    cprintf(ch, "your foes head, the weight finally brings them crashing down on top...\r\n");
    act("$n conjures a chilling storm of ice!\r\n", FALSE, ch, 0, 0, TO_ROOM);
    AreaEffectSpell(ch, dam, SPELL_ICE_STORM, 0, NULL);
}

void spell_poison_cloud(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_chain_lightning(char level, struct char_data *ch, struct char_data *victim,
			   struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_major_create(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_summon_obj(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_pword_blind(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_pword_kill(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_sending(char level, struct char_data *ch, struct char_data *victim,
		   struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_meteor_swarm(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    dam = dice((level / 2), 6) + level;
    cprintf(ch,
	    "You draw the symbols of fire and death in the air before you...\r\nWith a Word, you send it into your foes!!\r\n");
    act("$n sends intense balls of fire swirling all around the room!\r\n", FALSE, ch, 0, 0,
	TO_ROOM);
    AreaEffectSpell(ch, dam, SPELL_METEOR_SWARM, 0, NULL);
}

void spell_Create_Monster(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    struct affected_type                    af;
    struct char_data                       *mob = NULL;
    int                                     rnum = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    /*
     * load in a monster of the correct type, determined by level of the spell 
     */

    /*
     * really simple to start out with 
     */

    if (level <= 5) {
	rnum = number(1, 10) + 200;
	mob = read_mobile(rnum, VIRTUAL);
    } else if (level <= 7) {
	rnum = number(1, 10) + 210;
	mob = read_mobile(rnum, VIRTUAL);
    } else if (level <= 9) {
	rnum = number(1, 10) + 220;
	mob = read_mobile(rnum, VIRTUAL);
    } else if (level <= 11) {
	rnum = number(1, 10) + 230;
	mob = read_mobile(rnum, VIRTUAL);
    } else if (level <= 13) {
	rnum = number(1, 10) + 240;
	mob = read_mobile(rnum, VIRTUAL);
    } else if (level <= 15) {
	rnum = number(1, 8) + 250;
	mob = read_mobile(rnum, VIRTUAL);
    } else {
	rnum = number(0, 1) + 261;
	mob = read_mobile(rnum, VIRTUAL);
    }

    char_to_room(mob, ch->in_room);

    act("$n waves $s hand, and $N appears!", TRUE, ch, 0, mob, TO_ROOM);
    act("You wave your hand, and $N appears!", TRUE, ch, 0, mob, TO_CHAR);

    GET_EXP(mob) = 50 * GetMaxLevel(mob);
    if (number(0, 99) > 70 + GetMaxLevel(ch) - GetMaxLevel(mob)) {
	act("$N turns to $n and snarls.", FALSE, ch, 0, mob, TO_ROOM);
	act("$N turns to you and snarls!", TRUE, ch, 0, mob, TO_CHAR);
	AddHated(mob, ch);
	if (!IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	    SET_BIT(mob->specials.act, ACT_AGGRESSIVE);
	}
    } else {
	if (mob->master)
	    stop_follower(mob);
	af.type = SPELL_CHARM_PERSON;
	if (GET_INT(mob))
	    af.duration = 24 - GET_INT(mob);
	else
	    af.duration = 12;
	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(mob, &af);
	add_follower(mob, ch);
	if (IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	    REMOVE_BIT(mob->specials.act, ACT_AGGRESSIVE);
	}
    }

/*
 * if(!IS_SET(mob->specials.act, ACT_SENTINEL)) 
 * {
 * SET_BIT(mob->specials.act, ACT_SENTINEL);
 * }
 */

}

/*
 * either
 */

void spell_light(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    struct obj_data                        *tmp_obj = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/*
 * creates a ball of light in the hands.
 */
    CREATE(tmp_obj, struct obj_data, 1);

    clear_object(tmp_obj);

    tmp_obj->name = strdup("ball light");
    tmp_obj->short_description = strdup("A ball of light");
    tmp_obj->description = strdup("There is a ball of light on the ground here.");

    tmp_obj->obj_flags.type_flag = ITEM_LIGHT;
    tmp_obj->obj_flags.wear_flags = ITEM_TAKE | ITEM_HOLD;
    tmp_obj->obj_flags.value[2] = 24;
    tmp_obj->obj_flags.weight = 1;
    tmp_obj->obj_flags.cost = 10;
    tmp_obj->obj_flags.cost_per_day = 1;

    tmp_obj->next = object_list;
    object_list = tmp_obj;

    obj_to_char(tmp_obj, ch);

    tmp_obj->item_number = -1;

    act("$n intones a magic word and $p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_ROOM);
    act("With a flick of your wrist, $p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_CHAR);
}

void spell_fly(char level, struct char_data *ch, struct char_data *victim, struct obj_data *obj)
{
    struct affected_type                    af;
    int                                     dur = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_AFFECTED(victim, AFF_FLYING)) {
	cprintf(ch, "You are already flying....\r\n");
	return;
    }
    cprintf(victim, "Your feet begin to inch above the ground!\r\n");

    if (victim != ch)
	act("$N's feet rise off the ground.", TRUE, ch, 0, victim, TO_CHAR);
    else
	cprintf(ch, "Your feet rise up off the ground.");

    act("$N's feet rise off the ground.", TRUE, ch, 0, victim, TO_NOTVICT);

    dur = 10;

    switch (HowManyClasses(ch)) {
	case 1:
	    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 2 + 8;
	    break;
	case 2:
	    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 2 + 4;
	    break;
	case 3:
	    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 2;
	    break;
	case 4:
	    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 4 + 8;
	    break;
	default:
	    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 6 + 8;
	    break;
    }

    af.type = SPELL_FLY;
    af.duration = dur;
    af.modifier = 0;
    af.location = 0;
    af.bitvector = AFF_FLYING;
    affect_to_char(victim, &af);
}

void spell_refresh(char level, struct char_data *ch, struct char_data *victim,
		   struct obj_data *obj)
{
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    dam = dice(level, 4) + level;
    dam = MAX(dam, 30);

    if (GET_LEVEL(ch, MAGE_LEVEL_IND) > 1)
	dam >>= 1;

    if ((dam + GET_MOVE(victim)) > move_limit(victim))
	GET_MOVE(victim) = move_limit(victim);
    else
	GET_MOVE(victim) += dam;

    cprintf(victim, "You feel less tired\r\n");
}

void spell_water_breath(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    act("You feel fishy!", TRUE, ch, 0, victim, TO_VICT);
    if (victim != ch) {
	act("$N makes a face like a fish.", TRUE, ch, 0, victim, TO_CHAR);
    }
    act("$N makes a face like a fish.", TRUE, ch, 0, victim, TO_NOTVICT);

    af.type = SPELL_WATER_BREATH;
    af.duration = GET_LEVEL(ch, BestMagicClass(ch));
    af.modifier = 0;
    af.location = 0;
    af.bitvector = AFF_WATERBREATH;
    affect_to_char(victim, &af);
}

void spell_cont_light(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
/*
 * creates a ball of light in the hands.
 */
    struct obj_data                        *tmp_obj = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    CREATE(tmp_obj, struct obj_data, 1);

    clear_object(tmp_obj);

    tmp_obj->name = strdup("ball light");
    tmp_obj->short_description = strdup("A bright ball of light");
    tmp_obj->description = strdup("There is a bright ball of light on the ground here.");

    tmp_obj->obj_flags.type_flag = ITEM_LIGHT;
    tmp_obj->obj_flags.wear_flags = ITEM_TAKE | ITEM_HOLD;
    tmp_obj->obj_flags.value[2] = 72;
    tmp_obj->obj_flags.weight = 1;
    tmp_obj->obj_flags.cost = 40;
    tmp_obj->obj_flags.cost_per_day = 1;

    tmp_obj->next = object_list;
    object_list = tmp_obj;

    obj_to_char(tmp_obj, ch);

    tmp_obj->item_number = -1;

    act("$n intones a power word and $p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_ROOM);
    act("You twiddle your thumbs and $p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_CHAR);

}

void spell_animate_dead(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *corpse)
{
    struct char_data                       *mob = NULL;
    struct obj_data                        *obj_object = NULL;
    struct obj_data                        *next_obj = NULL;
    char                                    buf[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0";
    int                                     r_num = 100;       /* virtual # for zombie */
    int                                     k = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(corpse));

    if (!ch || !corpse)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/*
 * some sort of check for corpse hood
 */
    if ((GET_ITEM_TYPE(corpse) != ITEM_CONTAINER) || (!corpse->obj_flags.value[3])) {
	cprintf(ch, "The magic fails abruptly!\r\n");
	return;
    }
    mob = read_mobile(r_num, VIRTUAL);
    char_to_room(mob, ch->in_room);

    act("With mystic power, $n animates a corpse.", TRUE, ch, 0, 0, TO_ROOM);
    act("$N slowly rises from the ground.", FALSE, ch, 0, mob, TO_ROOM);

/*
 * zombie should be charmed and follower ch
 */

    GET_EXP(mob) = 50 * GetMaxLevel(ch);
    IS_CARRYING_W(mob) = 0;
    IS_CARRYING_N(mob) = 0;

/*
 * mob->killer = obj->killer;
 */
/*
 * take all from corpse, and give to zombie 
 */

    for (obj_object = corpse->contains; obj_object; obj_object = next_obj) {
	next_obj = obj_object->next_content;
	obj_from_obj(obj_object);
	obj_to_char(obj_object, mob);
    }
    do_wear(mob, "all", 0);

/*
 * set up descriptions and such
 */
    sprintf(buf, "%s is here, slowly animating\r\n", corpse->short_description);
    mob->player.long_descr = strdup(buf);

/*
 * set up hitpoints
 */

    mob->points.max_hit = dice(GetMaxLevel(ch) / 4, 8) + 10;
    mob->points.hit = mob->points.max_hit;

    for (k = MAGE_LEVEL_IND; k <= RANGER_LEVEL_IND; k++)
	mob->player.level[k] = ch->player.level[k] / 4;

    mob->player.sex = 0;

    GET_RACE(mob) = RACE_UNDEAD;
    mob->player.class = ch->player.class;
    if (number(0, 99) > 50 + GetMaxLevel(ch)) {
	act("$N turns to $n and snarls.", FALSE, ch, 0, mob, TO_ROOM);
	act("$N turns to you and snarls!", TRUE, ch, 0, mob, TO_CHAR);
	AddHated(mob, ch);
	if (!IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	    SET_BIT(mob->specials.act, ACT_AGGRESSIVE);
	}
    } else {
	SET_BIT(mob->specials.affected_by, AFF_CHARM);
	add_follower(mob, ch);
	if (IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	    REMOVE_BIT(mob->specials.act, ACT_AGGRESSIVE);
	}
    }

/*
 * get rid of corpse
 */
    extract_obj(corpse);
    GET_ALIGNMENT(ch) -= number(10, 100);
    if (GET_ALIGNMENT(ch) < -999)
	GET_ALIGNMENT(ch) = -1000;
}

void spell_know_alignment(char level, struct char_data *ch, struct char_data *victim,
			  struct obj_data *obj)
{
    int                                     ap = 0;
    char                                    name[100] = "\0\0\0\0\0\0\0";

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_NPC(victim))
	strcpy(name, victim->player.short_descr);
    else
	strcpy(name, GET_NAME(victim));

    ap = GET_ALIGNMENT(victim);

    if (ap > 700)
	cprintf(ch, "%s has an aura as white as the driven snow.\r\n", name);
    else if (ap > 350)
	cprintf(ch, "%s is of excellent moral character.\r\n", name);
    else if (ap > 100)
	cprintf(ch, "%s is often kind and thoughtful.\r\n", name);
    else if (ap > 25)
	cprintf(ch, "%s isn't a bad sort...\r\n", name);
    else if (ap > -25)
	cprintf(ch, "%s doesn't seem to have a firm moral commitment\r\n", name);
    else if (ap > -100)
	cprintf(ch, "%s isn't the worst you've come across\r\n", name);
    else if (ap > -350)
	cprintf(ch, "%s could be a little nicer, but who couldn't?\r\n", name);
    else if (ap > -700)
	cprintf(ch, "%s probably just had a bad childhood\r\n", name);
    else
	cprintf(ch, "I'd rather just not say anything at all about %s\r\n", name);
}

void spell_dispel_magic(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     yes = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/* gets rid of infravision, invisibility, detect, etc */

    if (!CheckKill(ch, victim))
	return;

    if ((GetMaxLevel(victim) <= GetMaxLevel(ch)))
	yes = TRUE;
    else
	yes = FALSE;

    if (affected_by_spell(victim, SPELL_INVISIBLE))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_INVISIBLE);
	    cprintf(victim, "You feel exposed.\r\n");
	}
    if (affected_by_spell(victim, SPELL_DETECT_INVISIBLE))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_DETECT_INVISIBLE);
	    cprintf(victim, "You feel less perceptive.\r\n");
	}
    if (affected_by_spell(victim, SPELL_DETECT_EVIL))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_DETECT_EVIL);
	    cprintf(victim, "You feel less morally alert.\r\n");
	}
    if (affected_by_spell(victim, SPELL_DETECT_MAGIC))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_DETECT_MAGIC);
	    cprintf(victim, "You stop noticing the magic in your life.\r\n");
	}
    if (affected_by_spell(victim, SPELL_SENSE_LIFE))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_SENSE_LIFE);
	    cprintf(victim, "You feel less in touch with living things.\r\n");
	}
    if (affected_by_spell(victim, SPELL_SANCTUARY)) {
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_SANCTUARY);
	    cprintf(victim, "You don't feel so invulnerable anymore.\r\n");
	    act("The white glow around $n's body fades.", FALSE, victim, 0, 0, TO_ROOM);
	}
	/*
	 *  aggressive Act.
	 */
	if ((victim->attackers < MAX_ATTACKERS) && (!victim->specials.fighting)
	    && (IS_NPC(victim))) {
	    set_fighting(victim, ch);
	}
    }
    if (IS_AFFECTED(victim, AFF_SANCTUARY)) {
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    REMOVE_BIT(victim->specials.affected_by, AFF_SANCTUARY);
	    cprintf(victim, "You don't feel so invulnerable anymore.\r\n");
	    act("The white glow around $n's body fades.", FALSE, victim, 0, 0, TO_ROOM);
	}
	/*
	 *  aggressive Act.
	 */
	if ((victim->attackers < MAX_ATTACKERS) && (!victim->specials.fighting)
	    && (IS_NPC(victim))) {
	    set_fighting(victim, ch);
	}
    }
    if (affected_by_spell(victim, SPELL_PROTECT_FROM_EVIL))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_PROTECT_FROM_EVIL);
	    cprintf(victim, "You feel less morally protected.\r\n");
	}
    if (affected_by_spell(victim, SPELL_INFRAVISION))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_INFRAVISION);
	    cprintf(victim, "Your sight grows dimmer.\r\n");
	}
    if (affected_by_spell(victim, SPELL_SLEEP))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_SLEEP);
	    cprintf(victim, "You don't feel so tired.\r\n");
	}
    if (affected_by_spell(victim, SPELL_CHARM_PERSON))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_CHARM_PERSON);
	    stop_follower(victim);
	    cprintf(victim, "You feel less enthused about your master.\r\n");
	}
    if (affected_by_spell(victim, SPELL_WEAKNESS))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_WEAKNESS);
	    cprintf(victim, "You don't feel so weak.\r\n");
	}
    if (affected_by_spell(victim, SPELL_STRENGTH))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_STRENGTH);
	    cprintf(victim, "You don't feel so strong.\r\n");
	}
    if (affected_by_spell(victim, SPELL_ARMOR))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_ARMOR);
	    cprintf(victim, "You don't feel so well protected.\r\n");
	}
    if (affected_by_spell(victim, SPELL_DETECT_POISON))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_DETECT_POISON);
	    cprintf(victim, "You don't feel so sensitive to fumes.\r\n");
	}
    if (affected_by_spell(victim, SPELL_BLESS))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_BLESS);
	    cprintf(victim, "You don't feel so blessed.\r\n");
	}
    if (affected_by_spell(victim, SPELL_FLY))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_FLY);
	    cprintf(victim, "You don't feel lighter than air anymore.\r\n");
	}
    if (affected_by_spell(victim, SPELL_WATER_BREATH))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_WATER_BREATH);
	    cprintf(victim, "You don't feel so fishy anymore.\r\n");
	}
    if (affected_by_spell(victim, SPELL_FIRE_BREATH))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_FIRE_BREATH);
	    cprintf(victim, "You don't feel so fiery anymore.\r\n");
	}
    if (affected_by_spell(victim, SPELL_LIGHTNING_BREATH))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_LIGHTNING_BREATH);
	    cprintf(victim, "You don't feel so electric anymore.\r\n");
	}
    if (affected_by_spell(victim, SPELL_GAS_BREATH))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_GAS_BREATH);
	    cprintf(victim, "You don't have gas anymore.\r\n");
	}
    if (affected_by_spell(victim, SPELL_FROST_BREATH))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_FROST_BREATH);
	    cprintf(victim, "You don't feel so frosty anymore.\r\n");
	}
    if (affected_by_spell(victim, SPELL_FIRESHIELD))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_FIRESHIELD);
	    cprintf(victim, "You don't feel so firey anymore.\r\n");
	    act("The red glow around $n's body fades.", TRUE, ch, 0, 0, TO_ROOM);
	}
    if (affected_by_spell(victim, SPELL_FAERIE_FIRE))
	if (yes || !saves_spell(victim, SAVING_SPELL)) {
	    affect_from_char(victim, SPELL_FAERIE_FIRE);
	    cprintf(victim, "You don't feel so pink anymore.\r\n");
	    act("The pink glow around $n's body fades.", TRUE, ch, 0, 0, TO_ROOM);
	}
    if (level >= IMPLEMENTOR) {
	if (affected_by_spell(victim, SPELL_BLINDNESS)) {
	    if (yes || !saves_spell(victim, SAVING_SPELL)) {
		affect_from_char(victim, SPELL_BLINDNESS);
		cprintf(victim, "Your vision returns.\r\n");
	    }
	}
	if (affected_by_spell(victim, SPELL_PARALYSIS)) {
	    if (yes || !saves_spell(victim, SAVING_SPELL)) {
		affect_from_char(victim, SPELL_PARALYSIS);
		cprintf(victim, "You feel freedom of movement.\r\n");
	    }
	}
	if (affected_by_spell(victim, SPELL_POISON)) {
	    if (yes || !saves_spell(victim, SAVING_SPELL)) {
		affect_from_char(victim, SPELL_POISON);
	    }
	}
    }
}

void spell_paralyze(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;

    if (!IS_AFFECTED(victim, AFF_PARALYSIS)) {
	if (IsImmune(victim, IMM_HOLD)) {
	    FailPara(victim, ch);
	    return;
	}
	if (IsResist(victim, IMM_HOLD)) {
	    if (saves_spell(victim, SAVING_PARA)) {
		FailPara(victim, ch);
		return;
	    }
	    if (saves_spell(victim, SAVING_PARA)) {
		FailPara(victim, ch);
		return;
	    }
	} else if (!IsSusc(victim, IMM_HOLD)) {
	    if (saves_spell(victim, SAVING_PARA)) {
		FailPara(victim, ch);
		return;
	    }
	}
	af.type = SPELL_PARALYSIS;
	af.duration = dice(1, 6);
	af.modifier = 0;
	af.location = APPLY_NONE;
	af.bitvector = AFF_PARALYSIS;
	affect_join(victim, &af, FALSE, FALSE);

	act("Your limbs freeze in place", FALSE, victim, 0, 0, TO_CHAR);
	act("$n is paralyzed!", TRUE, victim, 0, 0, TO_ROOM);
	GET_POS(victim) = POSITION_STUNNED;
    } else {
	cprintf(victim, "Someone tries to paralyze you AGAIN!\r\n");
    }
}

void spell_fear(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;

    if (GetMaxLevel(ch) >= GetMaxLevel(victim) - 2) {
	if (!saves_spell(victim, SAVING_SPELL)) {

/* 
 * af.type      = SPELL_FEAR;
 * af.duration  = 4+level;
 * af.modifier  = 0;
 * af.location  = APPLY_NONE;
 * af.bitvector = 0;
 * affect_join(victim, &af, FALSE, FALSE);
 */
	    do_flee(victim, "", 0);

	} else {
	    cprintf(victim, "You feel afraid, but the effect fades.\r\n");
	    return;
	}
    }
}

void spell_prot_align_group(char level, struct char_data *ch, struct char_data *victim,
			    struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_calm(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/* 
 * removes aggressive bit from monsters 
 */

    if (IS_NPC(victim)) {
	if (IS_SET(victim->specials.act, ACT_AGGRESSIVE)) {
	    if (!saves_spell(victim, SAVING_PARA)) {
		REMOVE_BIT(victim->specials.act, ACT_AGGRESSIVE);
	    } else {
		FailCalm(victim, ch);
	    }
	} else {
	    cprintf(victim, "You feel calm\r\n");
	}
    } else {
	cprintf(victim, "You feel calm.\r\n");
    }
}

void spell_conjure_elemental(char level, struct char_data *ch, struct char_data *victim,
			     struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || !obj)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;
    /*
     *   victim, in this case, is the elemental
     *   object could be the sacrificial object
     */

    /*
     * ** objects:
     * **     fire  : red stone
     * **     water : pale blue stone
     * **     earth : grey stone
     * **     air   : clear stone
     */

    act("$n gestures, and a cloud of smoke appears", TRUE, ch, 0, 0, TO_ROOM);
    act("$n gestures, and a cloud of smoke appears", TRUE, ch, 0, 0, TO_CHAR);
    act("$p explodes with a loud BANG!", TRUE, ch, obj, 0, TO_ROOM);
    act("$p explodes with a loud BANG!", TRUE, ch, obj, 0, TO_CHAR);
    obj_from_char(obj);
    extract_obj(obj);
    char_to_room(victim, ch->in_room);
    act("Out of the smoke, $N emerges", TRUE, ch, 0, victim, TO_NOTVICT);

    /*
     * charm them for a while 
     */
    if (victim->master)
	stop_follower(victim);

    add_follower(victim, ch);

    af.type = SPELL_CHARM_PERSON;
    af.duration = 24;
    af.modifier = 0;
    af.location = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char(victim, &af);
}

void spell_faerie_fire(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!CheckKill(ch, victim))
	return;

    if (affected_by_spell(victim, SPELL_FAERIE_FIRE)) {
	cprintf(ch, "Nothing new seems to happen");
	return;
    }
    act("$n points at $N.", TRUE, ch, 0, victim, TO_ROOM);
    act("You point at $N.", TRUE, ch, 0, victim, TO_CHAR);
    act("$N is surrounded by a pink outline", TRUE, ch, 0, victim, TO_ROOM);
    act("$N is surrounded by a pink outline", TRUE, ch, 0, victim, TO_CHAR);

    af.type = SPELL_FAERIE_FIRE;
    af.duration = level / 3;
    af.modifier = 10;
    af.location = APPLY_ARMOR;
    af.bitvector = 0;

    affect_to_char(victim, &af);

}

void spell_faerie_fog(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct char_data                       *tmp_victim = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    act("$n snaps $s fingers, and a cloud of purple smoke billows forth",
	TRUE, ch, 0, 0, TO_ROOM);
    act("You snap your fingers, and a cloud of purple smoke billows forth",
	TRUE, ch, 0, 0, TO_CHAR);

    for (tmp_victim = real_roomp(ch->in_room)->people; tmp_victim;
	 tmp_victim = tmp_victim->next_in_room) {
	if ((ch->in_room == tmp_victim->in_room) && (ch != tmp_victim)) {
	    if (IS_IMMORTAL(tmp_victim))
		if (tmp_victim->invis_level > GetMaxLevel(ch))
		    break;
	    if (!in_group(ch, tmp_victim)) {
		if (IS_AFFECTED(tmp_victim, AFF_INVISIBLE)) {
		    if (saves_spell(tmp_victim, SAVING_SPELL)) {
			REMOVE_BIT(tmp_victim->specials.affected_by, AFF_INVISIBLE);
			act("$n is briefly revealed, but dissapears again.",
			    TRUE, tmp_victim, 0, 0, TO_ROOM);
			act("You are briefly revealed, but dissapear again.",
			    TRUE, tmp_victim, 0, 0, TO_CHAR);
			SET_BIT(tmp_victim->specials.affected_by, AFF_INVISIBLE);
		    } else {
			REMOVE_BIT(tmp_victim->specials.affected_by, AFF_INVISIBLE);
			act("$n is revealed!", TRUE, tmp_victim, 0, 0, TO_ROOM);
			act("You are revealed!", TRUE, tmp_victim, 0, 0, TO_CHAR);
		    }
		}
	    }
	}
    }
}

void spell_cacaodemon(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim || !obj)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    act("$n gestures, and a black cloud of smoke appears", TRUE, ch, 0, 0, TO_ROOM);
    act("$n gestures, and a black cloud of smoke appears", TRUE, ch, 0, 0, TO_CHAR);
    act("$p bursts into flame and disintegrates!", TRUE, ch, obj, 0, TO_ROOM);
    act("$p bursts into flame and disintegrates!", TRUE, ch, obj, 0, TO_CHAR);
    obj_from_char(obj);
    extract_obj(obj);
    char_to_room(victim, ch->in_room);

    act("With an evil laugh, $N emerges from the smoke", TRUE, ch, 0, victim, TO_NOTVICT);

    /*
     * charm them for a while 
     */
    if (victim->master)
	stop_follower(victim);

    add_follower(victim, ch);

    af.type = SPELL_CHARM_PERSON;
    af.duration = level;
    af.modifier = 0;
    af.location = 0;
    af.bitvector = AFF_CHARM;

    affect_to_char(victim, &af);

    if (IS_SET(victim->specials.act, ACT_AGGRESSIVE))
	REMOVE_BIT(victim->specials.act, ACT_AGGRESSIVE);

    if (!IS_SET(victim->specials.act, ACT_SENTINEL))
	SET_BIT(victim->specials.act, ACT_SENTINEL);

}

/*
 * neither
 */

void spell_improved_identify(char level, struct char_data *ch, struct char_data *victim,
			     struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));
}

void spell_geyser(char level, struct char_data *ch, struct char_data *victim,
		  struct obj_data *obj)
{
    int                                     dam = 0;
    struct char_data                       *tmp_victim = NULL;
    struct char_data                       *temp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (ch->in_room < 0)
	return;
    dam = dice(level, 3);

    act("The Geyser erupts in a huge column of steam!\r\n", FALSE, ch, 0, 0, TO_ROOM);

    for (tmp_victim = real_roomp(ch->in_room)->people; tmp_victim; tmp_victim = temp) {
	temp = tmp_victim->next_in_room;
	if ((ch != tmp_victim) && (ch->in_room == tmp_victim->in_room)) {
	    if ((GetMaxLevel(tmp_victim) < LOW_IMMORTAL) || (IS_NPC(tmp_victim))) {
		damage(ch, tmp_victim, dam, SPELL_GEYSER);
		act("You are seared by the boiling water!!\r\n", FALSE, ch, 0, tmp_victim,
		    TO_VICT);
	    } else {
		act("You are almost seared by the boiling water!!\r\n",
		    FALSE, ch, 0, tmp_victim, TO_VICT);
	    }
	}
    }
}

void spell_green_slime(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    int                                     dam = 0;
    int                                     hpch = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    hpch = GET_MAX_HIT(ch);
    if (hpch < 10)
	hpch = 10;

    dam = (int)(hpch / 10);

    if (saves_spell(victim, SAVING_BREATH))
	dam >>= 1;

    cprintf(victim, "You are attacked by green slime!\r\n");

    damage(ch, victim, dam, SPELL_GREEN_SLIME);

}

/*
 * file: magic3.c , Implementation of (new)spells.        Part of DIKUMUD
 * Usage : The actual effect of magic.
 */

/*
 *
 *  Start of new spells for WileyIIMud - Cyric
 *
 *
 */

void spell_fly_group(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
    struct affected_type                    af;
    struct char_data                       *tch = NULL;
    int                                     dur = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (real_roomp(ch->in_room) == NULL)
	return;

    for (tch = real_roomp(ch->in_room)->people; tch; tch = tch->next_in_room) {
	if (in_group(ch, tch)) {
	    if (tch != ch) {
		act("Your feet rise off the ground!", TRUE, ch, 0, tch, TO_VICT);
		act("$N's feet rise off the ground.", TRUE, ch, 0, tch, TO_CHAR);
	    } else {
		cprintf(ch, "Your feet rise up off the ground.");
	    }
	    act("$N's feet rise off the ground.", TRUE, ch, 0, tch, TO_NOTVICT);

	    dur = 10;

	    switch (HowManyClasses(ch)) {
		case 1:
		    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 2 + 8;
		    break;
		case 2:
		    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 2 + 4;
		    break;
		case 3:
		    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 2;
		    break;
		case 4:
		    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 4 + 8;
		    break;
		default:
		    dur = GET_LEVEL(ch, BestMagicClass(ch)) / 6 + 8;
		    break;
	    }

	    af.type = SPELL_FLY;
	    af.duration = dur;
	    af.modifier = 0;
	    af.location = 0;
	    af.bitvector = AFF_FLYING;
	    affect_to_char(tch, &af);
	}
    }
}

void spell_aid(char level, struct char_data *ch, struct char_data *victim, struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(victim, SPELL_AID)) {
	cprintf(ch, "Already in effect\r\n");
	return;
    }
    GET_HIT(victim) += number(2, 8);

    update_pos(victim);

    act("$n looks aided", FALSE, victim, 0, 0, TO_ROOM);
    cprintf(victim, "You feel better!\r\n");

    af.type = SPELL_AID;
    af.duration = 10;
    af.modifier = 1;
    af.location = APPLY_HITROLL;
    af.bitvector = 0;
    affect_to_char(victim, &af);
}

void spell_goodberry(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
    struct obj_data                        *tmp_obj = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    CREATE(tmp_obj, struct obj_data, 1);
    clear_object(tmp_obj);

    tmp_obj->name = strdup("berry blue blueberry");
    tmp_obj->short_description = strdup("a plump blueberry");
    tmp_obj->description = strdup("A scrumptions blueberry lies here.");

    tmp_obj->obj_flags.type_flag = ITEM_FOOD;
    tmp_obj->obj_flags.wear_flags = ITEM_TAKE | ITEM_HOLD;
    tmp_obj->obj_flags.value[0] = 10;
    tmp_obj->obj_flags.weight = 5;
    tmp_obj->obj_flags.cost = 1;
    tmp_obj->obj_flags.cost_per_day = 1000;

    /*
     * give it a cure light wounds spell effect
     */

    SET_BIT(tmp_obj->obj_flags.extra_flags, ITEM_MAGIC);

    tmp_obj->affected[0].location = APPLY_EAT_SPELL;
    tmp_obj->affected[0].modifier = SPELL_CURE_LIGHT;

    tmp_obj->next = object_list;
    object_list = tmp_obj;

    obj_to_char(tmp_obj, ch);

    tmp_obj->item_number = -1;

    act("$p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_ROOM);
    act("$p suddenly appears in your hand.", TRUE, ch, tmp_obj, 0, TO_CHAR);
}

#ifdef DRUID_WORKING

void spell_tree_travel(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!affected_by_spell(ch, SPELL_TREE_TRAVEL)) {
	af.type = SPELL_TREE_TRAVEL;

	af.duration = 24;
	af.modifier = -5;
	af.location = APPLY_AC;
	af.bitvector = AFF_TREE_TRAVEL;
	affect_to_char(victim, &af);

	cprintf(victim, "You feel as one with the trees... Groovy!\r\n");
    } else {
	cprintf(ch, "Nothing seems to happen\r\n");
    }

}

void spell_transport_via_plant(char level, struct char_data *ch, struct char_data *victim,
			       struct obj_data *obj)
{
    struct room_data                       *rp = NULL;
    struct obj_data                        *o = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !obj)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    /*
     * find the tree in the room 
     */

    rp = real_roomp(ch->in_room);
    for (o = rp->contents; o; o = o->next_content) {
	if (ITEM_TYPE(o) == ITEM_TREE)
	    break;
    }

    if (!o) {
	cprintf(ch, "You need to have a tree nearby\r\n");
	return;
    }
    if (ITEM_TYPE(obj) != ITEM_TREE) {
	cprintf(ch, "Thats not a tree!\r\n");
	return;
    }
    if (obj->in_room < 0) {
	cprintf(ch, "That tree is nowhere to be found\r\n");
	return;
    }
    if (!real_roomp(obj->in_room)) {
	cprintf(ch, "That tree is nowhere to be found\r\n");
	return;
    }
    act("$n touches $p, and slowly vanishes within!", FALSE, ch, o, 0, TO_ROOM);
    act("You touch $p, and join your forms.", FALSE, ch, o, 0, TO_CHAR);
    char_from_room(ch);
    char_to_room(ch, obj->in_room);
    act("$p rustles slightly, and $n magically steps from within!", FALSE, ch, obj, 0, TO_ROOM);
    act("You are instantly transported to $p!", FALSE, ch, obj, 0, TO_CHAR);
    do_look(ch, "", 0);

}

void spell_speak_with_plants(char level, struct char_data *ch, struct char_data *victim,
			     struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !obj)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (ITEM_TYPE(obj) != ITEM_TREE) {
	cprintf(ch, "Sorry, you can't talk to that sort of thing\r\n");
	return;
    }
    act("%s says 'Hi $n, how ya doin?'", FALSE, ch, obj, 0, TO_CHAR, fname(obj->name));
    act("$p rustles slightly.", FALSE, ch, obj, 0, TO_ROOM);

}

#define TREE 6110

void spell_changestaff(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;
    struct obj_data                        *s = NULL;
    struct char_data                       *t = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    /*
     * player must be holding staff at the time 
     */

    if (!ch->equipment[HOLD]) {
	cprintf(ch, "You must be holding a staff!\r\n");
	return;
    }
    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    s = unequip_char(ch, HOLD);
    if (ITEM_TYPE(s) != ITEM_STAFF) {
	act("$p is not sufficient to complete this spell", FALSE, ch, s, 0, TO_CHAR);
	extract_obj(s);
	return;
    }
    if (!s->obj_flags.value[2]) {
	act("$p is not sufficiently powerful to complete this spell", FALSE, ch, s, 0, TO_CHAR);
	extract_obj(s);
	return;
    }
    act("$p vanishes in a burst of flame!", FALSE, ch, s, 0, TO_ROOM);
    act("$p vanishes in a burst of flame!", FALSE, ch, s, 0, TO_CHAR);

    t = read_mobile(TREE, VIRTUAL);
    char_to_room(t, ch->in_room);

    act("$n springs up in front of you!", FALSE, t, 0, 0, TO_ROOM);

    af.type = SPELL_CHARM_PERSON;

    if (IS_PC(ch) || ch->master) {
	af.duration = 10;				       /* keep it shorter, so fewer big groups of mobs */

	af.duration += s->obj_flags.value[2];		       /* num charges */

	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(t, &af);
    } else {
	SET_BIT(t->specials.affected_by, AFF_CHARM);
    }
    add_follower(t, ch);

    extract_obj(s);

}

/* mage spells */
void spell_pword_kill(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (GET_MAX_HIT(victim) <= 80) {
	damage(ch, victim, GET_MAX_HIT(victim) * 12, SPELL_PWORD_KILL);
    } else {
	cprintf(ch, "They are too powerful to destroy this way\r\n");
    }

}

void spell_pword_blind(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (GET_MAX_HIT(victim) <= 100) {
	SET_BIT(victim->specials.affected_by, AFF_BLIND);
    } else {
	cprintf(ch, "They are too powerful to blind this way\r\n");
    }

}

void spell_chain_lightn(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    int                                     lev = level;
    struct char_data                       *t = NULL;
    struct char_data                       *next = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    /*
     * victim = levd6 damage 
     */
    damage(ch, victim, dice(lev, 6), SPELL_LIGHTNING_BOLT);
    lev--;

    for (t = real_roomp(ch->in_room)->people; t; t = next) {
	next = t->next_in_room;
	if (!in_group(ch, t) && t != victim && (!IS_IMMORTAL(t) || IS_IMMORTAL(ch))) {
	    damage(ch, t, dice(lev, 6), SPELL_LIGHTNING_BOLT);
	    lev--;
	}
    }
}

void spell_scare(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (GetMaxLevel(victim) <= 5)
	do_flee(victim, "", 0);
}

void spell_haste(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(victim, SPELL_HASTE)) {
	cprintf(ch, "already hasted\n");
	return;
    }
    if (IS_NPC(victim)) {
	cprintf(ch, "It doesn't seem to work\n");
	return;
    }
    if (IS_IMMUNE(victim, IMM_HOLD)) {
	act("$N seems to ignore your spell", FALSE, ch, 0, victim, TO_CHAR);
	act("$n just tried to haste you, but you ignored it.", FALSE, ch, 0, victim, TO_VICT);
	if (!in_group(ch, victim)) {
	    if (!IS_PC(ch))
		hit(victim, ch, TYPE_UNDEFINED);
	}
	return;
    }
    af.type = SPELL_HASTE;
    af.duration = level;
    af.modifier = 1;
    af.location = APPLY_HASTE;
    af.bitvector = 0;
    affect_to_char(victim, &af);

    cprintf(victim, "You feel fast!\r\n");
    if (!IS_NPC(victim))
	victim->player.time.birth -= SECS_PER_MUD_YEAR;
    else {
	if (victim->desc && victim->desc->original)
	    victim->desc->original->player.time.birth -= SECS_PER_MUD_YEAR;
    }

    if (!in_group(ch, victim)) {
	if (!IS_PC(ch))
	    hit(victim, ch, TYPE_UNDEFINED);
    }
}

void spell_slow(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(victim, SPELL_SLOW)) {
	cprintf(ch, "already slowed\n");
	return;
    }
    if (IS_IMMUNE(victim, IMM_HOLD)) {
	act("$N seems to ignore your spell", FALSE, ch, 0, victim, TO_CHAR);
	act("$n just tried to slow you, but you ignored it.", FALSE, ch, 0, victim, TO_VICT);
	if (!in_group(ch, victim)) {
	    if (!IS_PC(ch))
		hit(victim, ch, TYPE_UNDEFINED);
	}
	return;
    }
    af.type = SPELL_SLOW;
    af.duration = 10;
    af.modifier = 1;
    af.location = APPLY_SLOW;
    af.bitvector = 0;
    affect_to_char(victim, &af);

    cprintf(victim, "You feel very slow!\r\n");

    if (!in_group(ch, victim)) {
	if (!IS_PC(ch))
	    hit(victim, ch, TYPE_UNDEFINED);
    }
}

#define KITTEN  3090
#define PUPPY   3091
#define BEAGLE  3092
#define ROTT    3093
#define WOLF    3094

void spell_familiar(char level, struct char_data *ch, struct char_data **victim,
		    struct obj_data *obj)
{
    struct affected_type                    af;
    struct char_data                       *f = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(ch, SPELL_FAMILIAR)) {
	cprintf(ch, "You can't have more than 1 familiar per day\r\n");
	return;
    }
    /*
     * depending on the level, one of the pet shop kids.
     */

    if (level < 2)
	f = read_mobile(KITTEN, VIRTUAL);
    else if (level < 4)
	f = read_mobile(PUPPY, VIRTUAL);
    else if (level < 6)
	f = read_mobile(BEAGLE, VIRTUAL);
    else if (level < 8)
	f = read_mobile(ROTT, VIRTUAL);
    else
	f = read_mobile(WOLF, VIRTUAL);

    char_to_room(f, ch->in_room);

    af.type = SPELL_FAMILIAR;
    af.duration = 24;
    af.modifier = -1;
    af.location = APPLY_ARMOR;
    af.bitvector = 0;
    affect_to_char(ch, &af);

    act("$n appears in a flash of light!\r\n", FALSE, f, 0, 0, TO_ROOM);

    SET_BIT(f->specials.affected_by, AFF_CHARM);
    GET_EXP(f) = 0;
    add_follower(f, ch);
    IS_CARRYING_W(f) = 0;
    IS_CARRYING_N(f) = 0;

    *victim = f;

}

/* cleric */

void spell_holyword(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    int                                     lev = 0;
    int                                     t_align = 0;
    struct char_data                       *t = NULL;
    struct char_data                       *next = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;

    if (level > 0)
	t_align = -300;
    else {
	level = -level;
	t_align = 300;
    }

    for (t = real_roomp(ch->in_room)->people; t; t = next) {
	next = t->next_in_room;
	if ((!IS_IMMORTAL(t) || IS_IMMORTAL(ch)) && !IS_AFFECTED(t, AFF_SILENCE)) {
	    if (level > 0) {
		if (GET_ALIGNMENT(t) <= t_align) {
		    if ((lev = GetMaxLevel(t)) <= 4) {
			damage(ch, t, GET_MAX_HIT(t) * 20, SPELL_HOLY_WORD);
		    } else if (lev <= 8) {
			damage(ch, t, 1, SPELL_HOLY_WORD);
			spell_paralyze(level, ch, t, 0);
		    } else if (lev <= 12) {
			damage(ch, t, 1, SPELL_HOLY_WORD);
			spell_blindness(level, ch, t, 0);
		    } else if (lev <= 16) {
			damage(ch, t, 0, SPELL_HOLY_WORD);
			GET_POS(t) = POSITION_STUNNED;
		    }
		}
	    } else {
		if (GET_ALIGNMENT(t) >= t_align) {
		    if ((lev = GetMaxLevel(t)) <= 4) {
			damage(ch, t, GET_MAX_HIT(t) * 20, SPELL_UNHOLY_WORD);
		    } else if (lev <= 8) {
			damage(ch, t, 1, SPELL_UNHOLY_WORD);
			spell_paralyze(level, ch, t, 0);
		    } else if (lev <= 12) {
			damage(ch, t, 1, SPELL_UNHOLY_WORD);
			spell_blindness(level, ch, t, 0);
		    } else if (lev <= 16) {
			damage(ch, t, 1, SPELL_UNHOLY_WORD);
			GET_POS(t) = POSITION_STUNNED;
		    }
		}
	    }
	}
    }
}

#define GOLEM 38

void spell_golem(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    int                                     count = 0;
    int                                     armor = 0;
    struct char_data                       *gol = NULL;
    struct obj_data                        *helm = NULL;
    struct obj_data                        *jacket = NULL;
    struct obj_data                        *leggings = NULL;
    struct obj_data                        *sleeves = NULL;
    struct obj_data                        *gloves = NULL;
    struct obj_data                        *boots = NULL;
    struct obj_data                        *o = NULL;
    struct room_data                       *rp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/* you need:  helm, jacket, leggings, sleeves, gloves, boots */

    rp = real_roomp(ch->in_room);
    if (!rp)
	return;

    for (o = rp->contents; o; o = o->next_content) {
	if (ITEM_TYPE(o) == ITEM_ARMOR) {
	    if (IS_SET(o->obj_flags.wear_flags, ITEM_WEAR_HEAD)) {
		if (!helm) {
		    count++;
		    helm = o;
		    continue;				       /* next item */
		}
	    }
	    if (IS_SET(o->obj_flags.wear_flags, ITEM_WEAR_FEET)) {
		if (!boots) {
		    count++;
		    boots = o;
		    continue;				       /* next item */
		}
	    }
	    if (IS_SET(o->obj_flags.wear_flags, ITEM_WEAR_BODY)) {
		if (!jacket) {
		    count++;
		    jacket = o;
		    continue;				       /* next item */
		}
	    }
	    if (IS_SET(o->obj_flags.wear_flags, ITEM_WEAR_LEGS)) {
		if (!leggings) {
		    count++;
		    leggings = o;
		    continue;				       /* next item */
		}
	    }
	    if (IS_SET(o->obj_flags.wear_flags, ITEM_WEAR_ARMS)) {
		if (!sleeves) {
		    count++;
		    sleeves = o;
		    continue;				       /* next item */
		}
	    }
	    if (IS_SET(o->obj_flags.wear_flags, ITEM_WEAR_HANDS)) {
		if (!gloves) {
		    count++;
		    gloves = o;
		    continue;				       /* next item */
		}
	    }
	}
    }

    if (count < 6) {
	cprintf(ch, "You don't have all the correct pieces!\r\n");
	return;
    }
    if (count > 6) {
	cprintf(ch, "Smells like an error to me!\r\n");
	return;
    }
    if (!boots || !sleeves || !gloves || !helm || !jacket || !leggings) {
	/*
	 * shouldn't get this far 
	 */
	cprintf(ch, "You don't have all the correct pieces!\r\n");
	return;
    }
    gol = read_mobile(GOLEM, VIRTUAL);
    char_to_room(gol, ch->in_room);

    /*
     * add up the armor values in the pieces 
     */
    armor = boots->obj_flags.value[0];
    armor += helm->obj_flags.value[0];
    armor += gloves->obj_flags.value[0];
    armor += (leggings->obj_flags.value[0] * 2);
    armor += (sleeves->obj_flags.value[0] * 2);
    armor += (jacket->obj_flags.value[0] * 3);

    GET_AC(gol) -= armor;

    gol->points.max_hit = dice((armor / 6), 10) + GetMaxLevel(ch);
    GET_HIT(gol) = GET_MAX_HIT(gol);

    GET_LEVEL(gol, WARRIOR_LEVEL_IND) = (armor / 6);

    SET_BIT(gol->specials.affected_by, AFF_CHARM);
    GET_EXP(gol) = 0;
    IS_CARRYING_W(gol) = 0;
    IS_CARRYING_N(gol) = 0;

    gol->player.class = CLASS_WARRIOR;

    if (GET_LEVEL(gol, WARRIOR_LEVEL_IND) > 10)
	gol->mult_att += 0.5;

    /*
     * add all the effects from all the items to the golem 
     */
    AddAffects(gol, boots);
    AddAffects(gol, gloves);
    AddAffects(gol, jacket);
    AddAffects(gol, sleeves);
    AddAffects(gol, leggings);
    AddAffects(gol, helm);

    act("$n waves $s hand over a pile of armor on the floor", FALSE, ch, 0, 0, TO_ROOM);
    act("You wave your hands over the pile of armor", FALSE, ch, 0, 0, TO_CHAR);

    act("The armor flys together to form a humanoid figure!", FALSE, ch, 0, 0, TO_ROOM);

    act("$N is quickly assembled from the pieces", FALSE, ch, 0, gol, TO_CHAR);

    add_follower(gol, ch);

    extract_obj(helm);
    extract_obj(boots);
    extract_obj(gloves);
    extract_obj(leggings);
    extract_obj(sleeves);
    extract_obj(jacket);

}

/***************/

void spell_feeblemind(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;
    int                                     t = 0;
    int                                     i = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!saves_spell(victim, SAVING_SPELL)) {

	cprintf(victim, "You feel really really dumb\r\n");

	af.type = SPELL_FEEBLEMIND;
	af.duration = 24;
	af.modifier = -5;
	af.location = APPLY_INT;
	af.bitvector = 0;
	affect_to_char(victim, &af);

	af.type = SPELL_FEEBLEMIND;
	af.duration = 24;
	af.modifier = 70;
	af.location = APPLY_SPELLFAIL;
	af.bitvector = 0;
	affect_to_char(victim, &af);

	/*
	 * last, but certainly not least
	 */
	if (!victim->skills)
	    return;

	t = number(1, 100);

	while (1) {
	    for (i = 0; i < MAX_SKILLS; i++) {
		if (victim->skills[i].learned)
		    t--;
		if (t == 0) {
		    victim->skills[i].learned = 0;
		    victim->skills[i].flags = 0;
		    break;
		}
	    }
	}
    }
}

void spell_shillelagh(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    int                                     i = 0;
    int                                     count = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !obj)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!(MAX_OBJ_AFFECT >= 2))
	return;

    if ((GET_ITEM_TYPE(obj) == ITEM_WEAPON) && !IS_SET(obj->obj_flags.extra_flags, ITEM_MAGIC)) {

	if (!isname("club", obj->name)) {
	    cprintf(ch, "That isn't a club!\r\n");
	    return;
	}
	for (i = 0; i < MAX_OBJ_AFFECT; i++) {
	    if (obj->affected[i].location == APPLY_NONE)
		count++;
	    if (obj->affected[i].location == APPLY_HITNDAM ||
		obj->affected[i].location == APPLY_HITROLL ||
		obj->affected[i].location == APPLY_DAMROLL)
		return;
	}

	if (count < 2)
	    return;
	/*
	 * find the slots 
	 */
	i = getFreeAffSlot(obj);

	SET_BIT(obj->obj_flags.extra_flags, ITEM_MAGIC);

	obj->affected[i].location = APPLY_HITNDAM;
	obj->affected[i].modifier = 1;

	obj->obj_flags.value[1] = 2;
	obj->obj_flags.value[2] = 4;

	act("$p glows yellow.", FALSE, ch, obj, 0, TO_CHAR);
	SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_GOOD | ITEM_ANTI_EVIL);

    }
}

void spell_flame_blade(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct obj_data                        *tmp_obj = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (ch->equipment[WIELD]) {
	cprintf(ch, "You can't be wielding a weapon\r\n");
	return;
    }
    CREATE(tmp_obj, struct obj_data, 1);
    clear_object(tmp_obj);

    tmp_obj->name = strdup("blade flame");
    tmp_obj->short_description = strdup("a flame blade");
    tmp_obj->description = strdup("A flame blade burns brightly here");

    tmp_obj->obj_flags.type_flag = ITEM_WEAPON;
    tmp_obj->obj_flags.wear_flags = ITEM_TAKE | ITEM_WIELD;
    tmp_obj->obj_flags.value[0] = 0;
    tmp_obj->obj_flags.value[1] = 1;
    tmp_obj->obj_flags.value[2] = 4;
    tmp_obj->obj_flags.value[3] = 3;
    tmp_obj->obj_flags.weight = 1;
    tmp_obj->obj_flags.cost = 10;
    tmp_obj->obj_flags.cost_per_day = 1;

    /*
     * give it a cure light wounds spell effect
     */

    SET_BIT(tmp_obj->obj_flags.extra_flags, ITEM_MAGIC);

    tmp_obj->affected[0].location = APPLY_DAMROLL;
    tmp_obj->affected[0].modifier = 4;

    tmp_obj->next = object_list;
    object_list = tmp_obj;

    equip_char(ch, tmp_obj, WIELD);

    tmp_obj->item_number = -1;

    act("$p appears in your hand.", TRUE, ch, tmp_obj, 0, TO_CHAR);
    act("$p appears in $n's hand.", TRUE, ch, tmp_obj, 0, TO_ROOM);
}

void spell_animal_growth(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    if (!IsAnimal(victim)) {
	cprintf(ch, "Thats not an animal\r\n");
	return;
    }
    if (affected_by_spell(victim, SPELL_ANIMAL_GROWTH)) {
	act("$N is already affected by that spell", FALSE, ch, 0, victim, TO_CHAR);
	return;
    }
    if (GetMaxLevel(victim) * 2 > GetMaxLevel(ch)) {
	cprintf(ch, "You can't make it more powerful than you!\r\n");
	return;
    }
    if (IS_PC(victim)) {
	cprintf(ch, "It would be in bad taste to cast that on a player\r\n");
	return;
    }
    act("$n grows to double $s original size!", FALSE, victim, 0, 0, TO_ROOM);
    act("You grow to double your original size!", FALSE, victim, 0, 0, TO_CHAR);

    af.type = SPELL_ANIMAL_GROWTH;
    af.duration = 3;
    af.modifier = GET_MAX_HIT(victim);
    af.location = APPLY_HIT;
    af.bitvector = AFF_GROWTH;
    affect_to_char(victim, &af);

    af.type = SPELL_ANIMAL_GROWTH;
    af.duration = 3;
    af.modifier = 5;
    af.location = APPLY_HITNDAM;
    af.bitvector = 0;
    affect_to_char(victim, &af);

    af.type = SPELL_ANIMAL_GROWTH;
    af.duration = 3;
    af.modifier = 3;
    af.location = APPLY_SAVE_ALL;
    af.bitvector = 0;
    affect_to_char(victim, &af);
/*
 * 
 * GET_LEVEL(victim, WARRIOR_LEVEL_IND) = 2*GetMaxLevel(victim);
 */
}

void spell_insect_growth(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (GET_RACE(victim) != RACE_INSECT) {
	cprintf(ch, "Thats not an insect.\r\n");
	return;
    }
    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    if (affected_by_spell(victim, SPELL_INSECT_GROWTH)) {
	act("$N is already affected by that spell", FALSE, ch, 0, victim, TO_CHAR);
	return;
    }
    if (GetMaxLevel(victim) * 2 > GetMaxLevel(ch)) {
	cprintf(ch, "You can't make it more powerful than you!\r\n");
	return;
    }
    if (IS_PC(victim)) {
	cprintf(ch, "It would be in bad taste to cast that on a player\r\n");
	return;
    }
    act("$n grows to double $s original size!", FALSE, victim, 0, 0, TO_ROOM);
    act("You grow to double your original size!", FALSE, victim, 0, 0, TO_CHAR);

    af.type = SPELL_INSECT_GROWTH;
    af.duration = 3;
    af.modifier = GET_MAX_HIT(victim);
    af.location = APPLY_HIT;
    af.bitvector = AFF_GROWTH;
    affect_to_char(victim, &af);

    af.type = SPELL_INSECT_GROWTH;
    af.duration = 3;
    af.modifier = 5;
    af.location = APPLY_HITNDAM;
    af.bitvector = 0;
    affect_to_char(victim, &af);

    af.type = SPELL_INSECT_GROWTH;
    af.duration = 3;
    af.modifier = 3;
    af.location = APPLY_SAVE_ALL;
    af.bitvector = 0;
    affect_to_char(victim, &af);
/*
 * GET_LEVEL(victim, WARRIOR_LEVEL_IND) = 2*GetMaxLevel(victim);
 */
}

#define CREEPING_DEATH 39

void spell_creeping_death(char level, struct char_data *ch, struct char_data *victim, int dir)
{
    struct affected_type                    af;
    struct char_data                       *cd = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    /*
     * obj is really the direction that the death wishes to travel in 
     */

    cd = read_mobile(CREEPING_DEATH, VIRTUAL);
    if (!cd) {
	cprintf(ch, "None available\r\n");
	return;
    }
    char_to_room(cd, ch->in_room);
    cd->points.max_hit += (number(1, 4) * 100) + 600;

    cd->points.hit = cd->points.max_hit;

    act("$n makes a horrid coughing sound", FALSE, ch, 0, 0, TO_ROOM);
    cprintf(ch, "You feel an incredibly nasty feeling inside\r\n");

    act("A huge gout of poisonous insects spews forth from $n's mouth!",
	FALSE, ch, 0, 0, TO_ROOM);
    cprintf(ch, "A huge gout of insects spews out of your mouth!\r\n");
    cprintf(ch, "My GOD thats disgusting!!!!!!!!!!\r\n");

    act("The insects coalesce into a solid mass - $n", FALSE, ch, 0, 0, TO_ROOM);

    cd->act_ptr = dir;

    /*
     * move the creeping death in the proper direction 
     */

    do_move(cd, "", dir);

    GET_POS(ch) = POSITION_STUNNED;

    af.type = SPELL_CREEPING_DEATH;
    af.duration = 2;
    af.modifier = 10500;
    af.location = APPLY_SPELLFAIL;
    af.bitvector = 0;
    affect_to_char(ch, &af);

}

void spell_commune(char level, struct char_data *ch, struct char_data *victim,
		   struct obj_data *obj)
{
    struct char_data                       *c = NULL;
    struct room_data                       *rp = NULL;
    struct room_data                       *dp = NULL;
    char                                    buf[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0";
    char                                    buffer[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0";

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    /*
     * look up the creatures in the mob list, find the ones in this zone, in rooms that are outdoors, and tell the
     * caster about them 
     */

    dp = real_roomp(ch->in_room);
    if (!dp)
	return;
    if (IS_SET(dp->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    for (c = character_list; c; c = c->next) {
	rp = real_roomp(c->in_room);
	if (!rp)
	    return;

	if (rp->zone == dp->zone) {
	    if (!IS_SET(rp->room_flags, INDOORS)) {
		sprintf(buf, "%s is in %s\r\n",
			(IS_NPC(c) ? c->player.short_descr : GET_NAME(c)), rp->name);
		if (strlen(buf) + strlen(buffer) > MAX_STRING_LENGTH - 2)
		    break;
		strcat(buffer, buf);
		strcat(buffer, "\r");
	    }
	}
    }

    page_string(ch->desc, buffer, 1);

}

#define ANISUM1  9007
#define ANISUM2  9014
#define ANISUM3  9021

void spell_animal_summon(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    struct affected_type                    af;
    struct char_data                       *mob = NULL;
    int                                     num = 0;
    int                                     i = 0;
    struct room_data                       *rp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    /*
     * load in a monster of the correct type, determined by level of the spell 
     */

/* really simple to start out with */

    if ((rp = real_roomp(ch->in_room)) == NULL)
	return;

    if (IS_SET(rp->room_flags, TUNNEL)) {
	cprintf(ch, "There isn't enough room in here to summon that.\r\n");
	return;
    }
    if (IS_SET(rp->room_flags, INDOORS)) {
	cprintf(ch, "You can only do this outdoors\n");
	return;
    }
    if (affected_by_spell(ch, SPELL_ANIMAL_SUM_1)) {
	cprintf(ch, "You can only do this once every 48 hours!\r\n");
	return;
    }
    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    switch (level) {
	case 1:
	    num = ANISUM1;
	    break;
	case 2:
	    num = ANISUM2;
	    break;
	case 3:
	    num = ANISUM3;
	    break;
    }

    act("$n performs a complicated ritual!", TRUE, ch, 0, 0, TO_ROOM);
    act("You perform the ritual of summoning", TRUE, ch, 0, 0, TO_CHAR);

    for (i = 0; i < 3; i++) {

	mob = read_mobile(num + number(0, 5), VIRTUAL);

	if (!mob)
	    continue;

	char_to_room(mob, ch->in_room);
	act("$n strides into the room", FALSE, mob, 0, 0, TO_ROOM);

	/*
	 * charm them for a while 
	 */
	if (mob->master)
	    stop_follower(mob);

	add_follower(mob, ch);

	af.type = SPELL_CHARM_PERSON;

	if (IS_PC(ch) || ch->master) {
	    af.duration = 8;
	    af.modifier = 0;
	    af.location = 0;
	    af.bitvector = AFF_CHARM;
	    affect_to_char(mob, &af);

	} else {
	    SET_BIT(mob->specials.affected_by, AFF_CHARM);
	}

	if (IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	    REMOVE_BIT(mob->specials.act, ACT_AGGRESSIVE);
	}
	if (!IS_SET(mob->specials.act, ACT_SENTINEL)) {
	    SET_BIT(mob->specials.act, ACT_SENTINEL);
	}
    }

    af.type = SPELL_ANIMAL_SUM_1;
    af.duration = 48;
    af.modifier = 0;
    af.location = 0;
    af.bitvector = 0;
    affect_to_char(ch, &af);

}

#define FIRE_ELEMENTAL  40

void spell_elemental_summoning(char level, struct char_data *ch, struct char_data *victim,
			       int spell)
{
    int                                     vnum = 0;
    struct char_data                       *mob = NULL;
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(ch, spell)) {
	cprintf(ch, "You can only do this once per 24 hours\r\n");
	return;
    }
    vnum = spell - SPELL_FIRE_SERVANT;
    vnum += FIRE_ELEMENTAL;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    mob = read_mobile(vnum, VIRTUAL);

    if (!mob) {
	cprintf(ch, "None available\r\n");
	return;
    }
    act("$n performs a complicated ritual!", TRUE, ch, 0, 0, TO_ROOM);
    act("You perform the ritual of summoning", TRUE, ch, 0, 0, TO_CHAR);

    char_to_room(mob, ch->in_room);
    act("$n appears through a momentary rift in the ether!", FALSE, mob, 0, 0, TO_ROOM);

    /*
     * charm them for a while 
     */
    if (mob->master)
	stop_follower(mob);

    add_follower(mob, ch);

    af.type = SPELL_CHARM_PERSON;

    if (IS_PC(ch) || ch->master) {
	af.duration = 24;
	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(mob, &af);

    } else {
	SET_BIT(mob->specials.affected_by, AFF_CHARM);
    }

    af.type = spell;
    af.duration = 24;
    af.modifier = 0;
    af.location = 0;
    af.bitvector = 0;
    affect_to_char(ch, &af);

/*
 * adjust the bits...
 */

/*
 * get rid of aggressive, add sentinel
 */

    if (IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	REMOVE_BIT(mob->specials.act, ACT_AGGRESSIVE);
    }
    if (!IS_SET(mob->specials.act, ACT_SENTINEL)) {
	SET_BIT(mob->specials.act, ACT_SENTINEL);
    }
}

void spell_reincarnate(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct char_data                       *newch = NULL;
    struct char_file_u                      st;
    struct descriptor_data                 *d = NULL;
    FILE                                   *fl = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !obj)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    if (real_roomp(ch->in_room)->sector_type != SECT_FOREST) {
	cprintf(ch, "You must cast this spell in the forest!\r\n");
	return;
    }
    if (IS_CORPSE(obj)) {

	if (obj->char_vnum) {
	    cprintf(ch, "This spell only works on players\r\n");
	    return;
	}
	if (obj->char_f_pos) {

	    fl = fopen(PLAYER_FILE, "r+");
	    if (!fl) {
		log_error("player file");
	    }
	    fseek(fl, obj->char_f_pos * sizeof(struct char_file_u), 0);
	    fread(&st, sizeof(struct char_file_u), 1, fl);

	    /*
	     **   this is a serious kludge, and must be changed before multiple
	     **   languages can be implemented
	     */
	    if (st.talks[2] && st.abilities.con > 3) {
		st.points.exp *= 2;
		st.talks[2] = TRUE;
		st.abilities.con -= 1;

		st.race = GetNewRace(&st);

		act("The forest comes alive with the sounds of birds and animals",
		    TRUE, ch, 0, 0, TO_CHAR);
		act("The forest comes alive with the sounds of birds and animals",
		    TRUE, ch, 0, 0, TO_ROOM);
		act("$p dissappears in the blink of an eye.", TRUE, ch, obj, 0, TO_CHAR);
		act("$p dissappears in the blink of an eye.", TRUE, ch, obj, 0, TO_ROOM);
		GET_MANA(ch) = 1;
		GET_MOVE(ch) = 1;
		GET_HIT(ch) = 1;
		GET_POS(ch) = POSITION_SITTING;
		act("$n collapses from the effort!", TRUE, ch, 0, 0, TO_ROOM);
		cprintf(ch, "You collapse from the effort\r\n");

		fseek(fl, obj->char_f_pos * sizeof(struct char_file_u), 0);
		fwrite(&st, sizeof(struct char_file_u), 1, fl);

		ObjFromCorpse(obj);

		CREATE(newch, struct char_data, 1);

		clear_char(newch);

		store_to_char(&st, newch);

		reset_char(newch);

		newch->next = character_list;
		character_list = newch;

		char_to_room(newch, ch->in_room);
		newch->invis_level = 51;

		set_title(newch);
		GET_HIT(newch) = 1;
		GET_MANA(newch) = 1;
		GET_MOVE(newch) = 1;
		GET_POS(newch) = POSITION_SITTING;
		save_char(newch, AUTO_RENT);

		/*
		 * if they are in the descriptor list, suck them into the game 
		 */

		for (d = descriptor_list; d; d = d->next) {
		    if (d->character && (strcmp(GET_NAME(d->character), GET_NAME(newch)) == 0)) {
			if (STATE(d) != CON_PLAYING) {
			    free_char(d->character);
			    d->character = newch;
			    STATE(d) = CON_PLAYING;
			    newch->desc = d;
			    cprintf(newch, "You awake to find yourself changed\r\n");
			    break;
			}
		    }
		}

	    } else {
		cprintf(ch, "The spirit does not have the strength to be reincarnated\r\n");
	    }
	    FCLOSE(fl);
	}
    }
}

void spell_charm_veggie(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (victim == ch) {
	cprintf(ch, "You like yourself even better!\r\n");
	return;
    }
    if (!IsVeggie(victim)) {
	cprintf(ch, "This can only be used on plants!\r\n");
	return;
    }
    if (GetMaxLevel(victim) > GetMaxLevel(ch) + 10) {
	FailCharm(victim, ch);
	return;
    }
    if (!IS_AFFECTED(victim, AFF_CHARM) && !IS_AFFECTED(ch, AFF_CHARM)) {
	if (circle_follow(victim, ch)) {
	    cprintf(ch, "Sorry, following in circles can not be allowed.\r\n");
	    return;
	}
	if (IsImmune(victim, IMM_CHARM) || (WeaponImmune(victim))) {
	    FailCharm(victim, ch);
	    return;
	}
	if (IsResist(victim, IMM_CHARM)) {
	    if (saves_spell(victim, SAVING_PARA)) {
		FailCharm(victim, ch);
		return;
	    }
	    if (saves_spell(victim, SAVING_PARA)) {
		FailCharm(victim, ch);
		return;
	    }
	} else {
	    if (!IsSusc(victim, IMM_CHARM)) {
		if (saves_spell(victim, SAVING_PARA)) {
		    FailCharm(victim, ch);
		    return;
		}
	    }
	}

	if (victim->master)
	    stop_follower(victim);

	add_follower(victim, ch);

	af.type = SPELL_CHARM_PERSON;

	if (GET_INT(victim))
	    af.duration = 24 * 18 / GET_INT(victim);
	else
	    af.duration = 24 * 18;

	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(victim, &af);

	act("Isn't $n just such a nice fellow?", FALSE, ch, 0, victim, TO_VICT);
    }
}

void spell_veggie_growth(char level, struct char_data *ch, struct char_data *victim,
			 struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!IsVeggie(victim)) {
	cprintf(ch, "Thats not a plant-creature!\r\n");
	return;
    }
    if (affected_by_spell(victim, SPELL_VEGGIE_GROWTH)) {
	act("$N is already affected by that spell", FALSE, ch, 0, victim, TO_CHAR);
	return;
    }
    if (GetMaxLevel(victim) * 2 > GetMaxLevel(ch)) {
	cprintf(ch, "You can't make it more powerful than you!\r\n");
	return;
    }
    if (IS_PC(victim)) {
	cprintf(ch, "It would be in bad taste to cast that on a player\r\n");
	return;
    }
    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    act("$n grows to double $s original size!", FALSE, victim, 0, 0, TO_ROOM);
    act("You grow to double your original size!", FALSE, victim, 0, 0, TO_CHAR);

    af.type = SPELL_VEGGIE_GROWTH;
    af.duration = 2 * level;
    af.modifier = GET_MAX_HIT(victim);
    af.location = APPLY_HIT;
    af.bitvector = AFF_GROWTH;
    affect_to_char(victim, &af);

    af.type = SPELL_VEGGIE_GROWTH;
    af.duration = 2 * level;
    af.modifier = 5;
    af.location = APPLY_HITNDAM;
    af.bitvector = 0;
    affect_to_char(victim, &af);

    af.type = SPELL_VEGGIE_GROWTH;
    af.duration = 2 * level;
    af.modifier = 3;
    af.location = APPLY_SAVE_ALL;
    af.bitvector = 0;
    affect_to_char(victim, &af);

    GET_LEVEL(victim, WARRIOR_LEVEL_IND) = 2 * GetMaxLevel(victim);

}

#define SAPLING  45

void spell_tree(char level, struct char_data *ch, struct char_data *victim,
		struct obj_data *obj)
{
    struct char_data                       *mob = NULL;
    int                                     mobn = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    mobn = SAPLING;
    if (level > 20) {
	mobn++;
    }
    if (level > 30) {
	mobn++;
    }
    if (level > 40) {
	mobn++;
    }
    if (level > 48) {
	mobn++;
    }
    mob = read_mobile(mobn, VIRTUAL);
    if (mob) {
	spell_poly_self(level, ch, mob, 0);
    } else {
	cprintf(ch, "You couldn't summon an image of that creature\r\n");
    }
    return;

}

#define LITTLE_ROCK  50

void spell_animate_rock(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct char_data                       *mob = NULL;
    struct affected_type                    af;
    int                                     mobn = LITTLE_ROCK;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !obj)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (ITEM_TYPE(obj) != ITEM_ROCK) {
	cprintf(ch, "Thats not the right kind of rock\r\n");
	return;
    }
    /*
     * get the weight of the rock, make the follower based on the weight 
     */

    if (GET_OBJ_WEIGHT(obj) > 20)
	mobn++;
    if (GET_OBJ_WEIGHT(obj) > 40)
	mobn++;
    if (GET_OBJ_WEIGHT(obj) > 80)
	mobn++;
    if (GET_OBJ_WEIGHT(obj) > 160)
	mobn++;
    if (GET_OBJ_WEIGHT(obj) > 320)
	mobn++;

    mob = read_mobile(mobn, VIRTUAL);
    if (mob) {

	char_to_room(mob, ch->in_room);
	/*
	 * charm them for a while 
	 */
	if (mob->master)
	    stop_follower(mob);

	add_follower(mob, ch);

	af.type = SPELL_ANIMATE_ROCK;
	af.duration = 24;
	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(mob, &af);

	af.type = SPELL_CHARM_PERSON;

	if (IS_PC(ch) || ch->master) {
	    af.duration = 24;
	    af.modifier = 0;
	    af.location = 0;
	    af.bitvector = AFF_CHARM;
	    affect_to_char(mob, &af);

	} else {
	    SET_BIT(mob->specials.affected_by, AFF_CHARM);
	}

	/*
	 * get rid of aggressive, add sentinel
	 */

	if (IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	    REMOVE_BIT(mob->specials.act, ACT_AGGRESSIVE);
	}
	if (!IS_SET(mob->specials.act, ACT_SENTINEL)) {
	    SET_BIT(mob->specials.act, ACT_SENTINEL);
	}
	extract_obj(obj);

    } else {
	cprintf(ch, "Sorry, the spell isn't working today\r\n");
	return;
    }

}

void spell_travelling(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(victim, SPELL_TRAVELLING))
	return;

    af.type = SPELL_TRAVELLING;
    af.duration = level;
    af.modifier = 0;
    af.location = APPLY_NONE;
    af.bitvector = AFF_TRAVELLING;

    affect_to_char(victim, &af);
    act("$n seems fleet of foot", FALSE, victim, 0, 0, TO_ROOM);
    cprintf(victim, "You feel fleet of foot.\r\n");
}

void spell_animal_friendship(char level, struct char_data *ch, struct char_data *victim,
			     struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(ch, SPELL_ANIMAL_FRIENDSHIP)) {
	cprintf(ch, "You can only do this 1 time per day\r\n");
	return;
    }
    if (IS_GOOD(victim) || IS_EVIL(victim)) {
	cprintf(ch, "Only neutral mobs allowed\r\n");
	return;
    }
    if (!IsAnimal(victim)) {
	cprintf(ch, "Thats no animal!\r\n");
	return;
    }
    if (GetMaxLevel(ch) < GetMaxLevel(victim)) {
	cprintf(ch, "You do not have enough willpower to charm that yet\r\n");
	return;
    }
    if (GetMaxLevel(victim) > 10) {
	cprintf(ch, "That creature is too powerful to charm\r\n");
	return;
    }
    if (IsImmune(victim, IMM_CHARM)) {
	return;
    }
    if (!saves_spell(victim, SAVING_SPELL))
	return;

    if (victim->master)
	stop_follower(victim);

    add_follower(victim, ch);

    af.type = SPELL_ANIMAL_FRIENDSHIP;
    af.duration = 24;
    af.modifier = 0;
    af.location = APPLY_NONE;
    af.bitvector = 0;
    affect_to_char(ch, &af);

    af.type = SPELL_ANIMAL_FRIENDSHIP;
    af.duration = 24;
    af.modifier = 0;
    af.location = APPLY_NONE;
    af.bitvector = AFF_CHARM;
    affect_to_char(victim, &af);

    /*
     * get rid of aggressive, add sentinel
     */
    REMOVE_BIT(victim->specials.act, ACT_AGGRESSIVE);

    SET_BIT(victim->specials.act, ACT_SENTINEL);

}

void spell_invis_to_animals(char level, struct char_data *ch, struct char_data *victim,
			    struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!affected_by_spell(victim, SPELL_INVIS_TO_ANIMALS)) {

	act("$n seems to fade slightly.", TRUE, victim, 0, 0, TO_ROOM);
	cprintf(victim, "You vanish, sort of.\r\n");

	af.type = SPELL_INVIS_TO_ANIMALS;
	af.duration = 24;
	af.modifier = 0;
	af.location = APPLY_BV2;
	af.bitvector = AFF2_ANIMAL_INVIS;
	affect_to_char(victim, &af);
    }
}

void spell_slow_poison(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(victim, SPELL_POISON)) {

	act("$n seems to fade slightly.", TRUE, victim, 0, 0, TO_ROOM);
	cprintf(victim, "You feel a bit better!.\r\n");

	af.type = SPELL_SLOW_POISON;
	af.duration = 24;
	af.modifier = 0;
	af.location = 0;
	af.bitvector = 0;
	affect_to_char(victim, &af);
    }
}

void spell_snare(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    if (real_roomp(ch->in_room)->sector_type != SECT_FOREST) {
	cprintf(ch, "You must cast this spell in the forest!\r\n");
	return;
    }
    /*
     * if victim fails save, movement = 0 
     */
    if (!saves_spell(victim, SAVING_SPELL)) {
	act("Roots and vines entangle your feet!", FALSE, victim, 0, 0, TO_CHAR);
	act("Roots and vines entangle $n's feet!", FALSE, victim, 0, 0, TO_ROOM);
	GET_MOVE(victim) = 0;
    } else {
	FailSnare(ch, victim);
    }
}

void spell_entangle(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    if (real_roomp(ch->in_room)->sector_type != SECT_FOREST) {
	cprintf(ch, "You must cast this spell in the forest!\r\n");
	return;
    }
    /*
     * if victim fails save, paralyzed for a very short time 
     */
    if (!saves_spell(victim, SAVING_SPELL)) {
	act("Roots and vines entwine around you!", FALSE, victim, 0, 0, TO_CHAR);
	act("Roots and vines surround $n!", FALSE, victim, 0, 0, TO_ROOM);

	af.type = SPELL_ENTANGLE;
	af.duration = 1;
	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_PARALYSIS;
	affect_to_char(victim, &af);

    } else {
	FailSnare(ch, victim);
    }
}

void spell_barkskin(char level, struct char_data *ch, struct char_data *victim,
		    struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!affected_by_spell(victim, SPELL_BARKSKIN) && !affected_by_spell(victim, SPELL_ARMOR)) {

	af.type = SPELL_BARKSKIN;
	af.duration = 24;
	af.modifier = -10;
	af.location = APPLY_AC;
	af.bitvector = 0;
	affect_to_char(victim, &af);

	af.type = SPELL_BARKSKIN;
	af.duration = 24;
	af.modifier = -1;
	af.location = APPLY_SAVE_ALL;
	af.bitvector = 0;
	affect_to_char(victim, &af);

	af.type = SPELL_BARKSKIN;
	af.duration = 24;
	af.modifier = 1;
	af.location = APPLY_SAVING_SPELL;
	af.bitvector = 0;
	affect_to_char(victim, &af);

	cprintf(victim, "Your skin takes on a rough, bark-like texture.\r\n");
	act("$n's skin takes on a rough, bark-like texture", FALSE, ch, 0, 0, TO_ROOM);

    } else {
	cprintf(ch, "Nothing new seems to happen\r\n");
    }
}

void spell_gust_of_wind(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    struct char_data                       *tmp_victim = NULL;
    struct char_data                       *temp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    cprintf(ch, "You wave your hands, and a gust of wind boils forth!\r\n");
    act("$n sends a gust of wind towards you!\r\n", FALSE, ch, 0, 0, TO_ROOM);

    for (tmp_victim = real_roomp(ch->in_room)->people; tmp_victim; tmp_victim = temp) {
	temp = tmp_victim->next_in_room;
	if ((ch->in_room == tmp_victim->in_room) && (ch != tmp_victim)) {
	    if (IS_PC(tmp_victim) && IS_IMMORTAL(tmp_victim) && !IS_IMMORTAL(ch))
		return;
	    if (!in_group(ch, tmp_victim)) {
		if (saves_spell(tmp_victim, SAVING_SPELL))
		    continue;
		GET_POS(tmp_victim) = POSITION_SITTING;
	    } else {
		act("You are able to avoid the swirling gust\r\n", FALSE, ch, 0, tmp_victim,
		    TO_VICT);
	    }
	}
    }
}

void spell_silence(char level, struct char_data *ch, struct char_data *victim,
		   struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!affected_by_spell(victim, SPELL_SILENCE)) {
	if (!saves_spell(victim, SAVING_SPELL)) {
	    act("$n ceases to make noise!", TRUE, victim, 0, 0, TO_ROOM);
	    cprintf(victim, "You can't hear anything!.\r\n");

	    af.type = SPELL_SILENCE;
	    af.duration = level;
	    af.modifier = 0;
	    af.location = 0;
	    af.bitvector = AFF_SILENCE;
	    affect_to_char(victim, &af);
	} else {
	    cprintf(victim, "You feel quiet for a moment, but the effect fades\r\n");
	    if (!IS_PC(victim)) {
		if ((!victim->specials.fighting)) {
		    set_fighting(victim, ch);
		    if (mob_index[victim->nr].func) {
			(*mob_index[victim->nr].func) (victim, 0, "");
		    }
		}
	    }
	}
    }
}

void spell_warp_weapon(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!(ch && (victim || obj)))
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (!obj) {
	if (!victim->equipment[WIELD]) {
	    act("$N doesn't have a weapon wielded!", FALSE, ch, 0, victim, TO_CHAR);
	    return;
	}
	obj = victim->equipment[WIELD];
    }
    act("$p is warped and twisted by the power of the spell", FALSE, ch, obj, 0, TO_CHAR);
    act("$p is warped and twisted by the power of the spell", FALSE, ch, obj, 0, TO_ROOM);
    DamageOneItem(victim, BLOW_DAMAGE, obj);

    if (!IS_PC(victim))
	if (!victim->specials.fighting)
	    set_fighting(victim, ch);
}

void spell_heat_stuff(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(victim, SPELL_HEAT_STUFF)) {
	cprintf(victim, "Already affected\r\n");
	return;
    }
    if (HitOrMiss(ch, victim, CalcThaco(ch))) {
	af.type = SPELL_HEAT_STUFF;
	af.duration = level;
	af.modifier = -2;
	af.location = APPLY_DEX;
	af.bitvector = 0;
	affect_to_char(victim, &af);

	af.type = SPELL_HEAT_STUFF;
	af.duration = level;
	af.modifier = 0;
	af.location = APPLY_BV2;
	af.bitvector = AFF2_HEAT_STUFF;

	affect_to_char(victim, &af);
	cprintf(victim, "Your armor starts to sizzle and smoke\r\n");
	act("$N's armor starts to sizzle\r\n", FALSE, ch, 0, victim, TO_CHAR);
	act("$N's armor starts to sizzle\r\n", FALSE, ch, 0, victim, TO_NOTVICT);

	if (!IS_PC(victim))
	    if (!victim->specials.fighting)
		set_fighting(victim, ch);
    }
}

#define DUST_DEVIL 60

void spell_dust_devil(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    int                                     vnum = 0;
    struct char_data                       *mob = NULL;
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(ch, SPELL_DUST_DEVIL)) {
	cprintf(ch, "You can only do this once per 24 hours\r\n");
	return;
    }
    if (IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) {
	cprintf(ch, "You can't cast this spell indoors!\r\n");
	return;
    }
    vnum = DUST_DEVIL;

    mob = read_mobile(vnum, VIRTUAL);

    if (!mob) {
	cprintf(ch, "None available\r\n");
	return;
    }
    act("$n performs a complicated ritual!", TRUE, ch, 0, 0, TO_ROOM);
    act("You perform the ritual of summoning", TRUE, ch, 0, 0, TO_CHAR);

    char_to_room(mob, ch->in_room);
    act("$n appears through a momentary rift in the ether!", FALSE, mob, 0, 0, TO_ROOM);

    /*
     * charm them for a while 
     */
    if (mob->master)
	stop_follower(mob);

    add_follower(mob, ch);

    af.type = SPELL_CHARM_PERSON;

    if (IS_PC(ch) || ch->master) {
	af.duration = 24;
	af.modifier = 0;
	af.location = 0;
	af.bitvector = AFF_CHARM;
	affect_to_char(mob, &af);

    } else {
	SET_BIT(mob->specials.affected_by, AFF_CHARM);
    }

    af.type = SPELL_DUST_DEVIL;
    af.duration = 24;
    af.modifier = 0;
    af.location = 0;
    af.bitvector = 0;
    affect_to_char(ch, &af);

/*
 * adjust the bits...
 */

/*
 * get rid of aggressive, add sentinel
 */

    if (IS_SET(mob->specials.act, ACT_AGGRESSIVE)) {
	REMOVE_BIT(mob->specials.act, ACT_AGGRESSIVE);
    }
    if (!IS_SET(mob->specials.act, ACT_SENTINEL)) {
	SET_BIT(mob->specials.act, ACT_SENTINEL);
    }
}

void spell_sunray(char level, struct char_data *ch, struct char_data *victim,
		  struct obj_data *obj)
{
    struct char_data                       *t = NULL;
    struct char_data                       *n = NULL;
    int                                     dam = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    /*
     * blind all in room
     */
    for (t = real_roomp(ch->in_room)->people; t; t = n) {
	n = t->next_in_room;
	if (!in_group(ch, t) && (!IS_IMMORTAL(t) || IS_IMMORTAL(ch))) {
	    spell_blindness(level, ch, t, obj);
	    /*
	     * hit undead target
	     */
	    if (t == victim) {
		if (GET_RACE(victim) == RACE_UNDEAD || GET_RACE(victim) == RACE_VEGMAN) {
		    dam = dice(6, 8);
		    if (saves_spell(victim, SAVING_SPELL) && (GET_RACE(victim) != RACE_VEGMAN))
			dam >>= 1;
		    damage(ch, victim, dam, SPELL_SUNRAY);
		}
	    } else {
		/*
		 * damage other undead in room
		 */
		if (GET_RACE(t) == RACE_UNDEAD || GET_RACE(t) == RACE_VEGMAN) {
		    dam = dice(3, 6);
		    if (saves_spell(t, SAVING_SPELL) && (GET_RACE(t) != RACE_VEGMAN))
			dam = 0;
		    damage(ch, t, dam, SPELL_SUNRAY);
		}
	    }
	}
    }
}

void spell_know_monster(char level, struct char_data *ch, struct char_data *victim,
			struct obj_data *obj)
{
    char                                    buf[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    char                                    buf2[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    int                                     exp = 0;
    int                                     lev = 0;
    int                                     hits = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/*
 * depending on level, give info.. sometimes inaccurate
 */

    if (!IS_PC(victim)) {
	act("$N belongs to the %s race.", FALSE, ch, 0, victim, TO_CHAR,
	    RaceName[GET_RACE(victim)]);
	if (level > 5) {
	    exp = GetApprox(GET_EXP(victim), 40 + level);
	    act("$N is worth approximately %d experience", FALSE, ch, 0, victim, TO_CHAR, exp);
	}
	if (level > 10) {
	    lev = GetApprox(GetMaxLevel(victim), 40 + level);
	    act("$N fights like a %d level warrior, you think", FALSE, ch, 0, victim, TO_CHAR,
		lev);
	}
	if (level > 15) {
	    if (IS_SET(victim->hatefield, HATE_RACE)) {
		act("$n seems to hate the %s race", FALSE, ch, 0, victim, TO_CHAR,
		    RaceName[victim->hates.race]);
	    }
	    if (IS_SET(victim->hatefield, HATE_CLASS)) {
		sprintbit((unsigned)victim->hates.class, pc_class_types, buf2);
		act("$n seems to hate the %s class(es)", FALSE, ch, 0, victim, TO_CHAR, buf2);
	    }
	}
	if (level > 20) {
	    hits = GetApprox(GET_MAX_HIT(victim), 40 + level);
	    act("$N probably has about %d hit points", FALSE, ch, 0, victim, TO_CHAR, hits);
	}
	if (level > 25) {
	    if (victim->susc) {
		sprintbit(victim->susc, immunity_names, buf2);
		act("$N is susceptible to %s\r\n", FALSE, ch, 0, victim, TO_CHAR, buf2);
	    }
	}
	if (level > 30) {
	    if (victim->immune) {
		sprintbit(victim->immune, immunity_names, buf2);
		act("$N is resistant to %s\r\n", FALSE, ch, 0, victim, TO_CHAR, buf2);
	    }
	}
	if (level > 35) {
	    if (victim->M_immune) {
		sprintbit(victim->M_immune, immunity_names, buf2);
		act("$N is immune to %s\r\n", FALSE, ch, 0, victim, TO_CHAR, buf2);
	    }
	}
	if (level > 40) {
	    int                                     att;

	    att = GetApprox((int)victim->mult_att, 30 + level);
	    act("$N gets approx %d.0 attack(s) per round", FALSE, ch, 0, victim, TO_CHAR, att);
	}
	if (level > 45) {
	    int                                     no,
	                                            s;

	    no = GetApprox(victim->specials.damnodice, 30 + level);
	    s = GetApprox(victim->specials.damsizedice, 30 + level);

	    act("Each does about %dd%d points of damage", FALSE, ch, 0, victim, TO_CHAR, no, s);
	}
    } else {
	cprintf(ch, "Thats not a REAL monster\r\n");
	return;
    }

}

void spell_find_traps(char level, struct char_data *ch, struct char_data *victim,
		      struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/*
 * raise their detect traps skill
 */
    af.type = SPELL_FIND_TRAPS;
    af.duration = level;
    af.modifier = 50 + level;
    af.location = APPLY_FIND_TRAPS;
    af.bitvector = 0;
    affect_to_char(ch, &af);

}

void spell_firestorm(char level, struct char_data *ch, struct char_data *victim,
		     struct obj_data *obj)
{
/*
 * a-e -    2d8+level
 */
    int                                     dam = 0;
    struct char_data                       *tmp_victim = NULL;
    struct char_data                       *temp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    dam = dice(2, 8) + level + 1;

    cprintf(ch, "Searing flame surround you!\r\n");
    act("$n sends a firestorm whirling across the room!\r\n", FALSE, ch, 0, 0, TO_ROOM);

    for (tmp_victim = real_roomp(ch->in_room)->people; tmp_victim; tmp_victim = temp) {
	temp = tmp_victim->next_in_room;
	if ((ch->in_room == tmp_victim->in_room) && (ch != tmp_victim)) {
	    if (IS_PC(tmp_victim) && IS_IMMORTAL(tmp_victim) && !IS_IMMORTAL(ch))
		return;
	    if (!in_group(ch, tmp_victim)) {
		act("You are seared by the burning flame!\r\n", FALSE, ch, 0, tmp_victim,
		    TO_VICT);
		if (saves_spell(tmp_victim, SAVING_SPELL))
		    dam >>= 1;
		MissileDamage(ch, tmp_victim, dam, SPELL_BURNING_HANDS);
	    } else {
		act("You are able to avoid the flames!\r\n", FALSE, ch, 0, tmp_victim, TO_VICT);
	    }
	}
    }
}

void spell_teleport_wo_error(char level, struct char_data *ch, struct char_data *victim,
			     struct obj_data *obj)
{
    int                                     location = 0;
    struct room_data                       *rp = NULL;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch || !victim)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/* replaces the current functionality of astral walk */

    location = victim->in_room;
    rp = real_roomp(location);

    if (GetMaxLevel(victim) > MAX_MORT ||
	!rp ||
	IS_SET(rp->room_flags, PRIVATE) ||
	IS_SET(rp->room_flags, NO_SUM) ||
	IS_SET(rp->room_flags, NO_MAGIC) ||
	(IS_SET(rp->room_flags, TUNNEL) && (MobCountInRoom(rp->people) > rp->moblim))) {
	cprintf(ch, "You failed.\r\n");
	return;
    }
    if (!IsOnPmp(location)) {
	cprintf(ch, "That place is on an extra-dimensional plane!\n");
	return;
    }
    if (!IsOnPmp(ch->in_room)) {
	cprintf(ch, "You're on an extra-dimensional plane!\r\n");
	return;
    }
    if (dice(1, 20) == 20) {
	cprintf(ch, "You fail the magic, and spin out of control!\r\n");
	spell_teleport(level, ch, ch, 0);
	return;
    } else {
	act("$n opens a door to another dimension and steps through!", FALSE, ch, 0, 0,
	    TO_ROOM);
	char_from_room(ch);
	char_to_room(ch, location);
	act("You are blinded for a moment as $n appears in a flash of light!",
	    FALSE, ch, 0, 0, TO_ROOM);
	do_look(ch, "", 15);
	check_falling(ch);

	if (IS_SET(real_roomp(ch->in_room)->room_flags, DEATH)
	    && GetMaxLevel(ch) < LOW_IMMORTAL) {
	    NailThisSucker(ch);
	    return;
	}
    }

}

#define PORTAL 31

void spell_portal(char level, struct char_data *ch, struct char_data *tmp_ch,
		  struct obj_data *obj)
{
    /*
     * create a magic portal 
     */
    struct obj_data                        *tmp_obj = NULL;
    struct extra_descr_data                *ed = NULL;
    struct room_data                       *rp = NULL;
    char                                    buf[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    rp = real_roomp(tmp_ch->in_room);
    tmp_obj = read_object(PORTAL, VIRTUAL);
    if (!rp || !tmp_obj) {
	cprintf(ch, "The magic fails\r\n");
	return;
    }
    sprintf(buf, "Through the mists of the portal, you can faintly see %s", rp->name);

    CREATE(ed, struct extra_descr_data, 1);
    ed->next = tmp_obj->ex_description;
    tmp_obj->ex_description = ed;
    CREATE(ed->keyword, char, strlen        (tmp_obj->name) + 1);

    strcpy(ed->keyword, tmp_obj->name);
    ed->description = strdup(buf);

    tmp_obj->obj_flags.value[0] = level / 5;
    tmp_obj->obj_flags.value[1] = tmp_ch->in_room;

    obj_to_room(tmp_obj, ch->in_room);

    act("$p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_ROOM);
    act("$p suddenly appears.", TRUE, ch, tmp_obj, 0, TO_CHAR);

}

#define MOUNT_ONE 65
#define MOUNT_GOOD 69
#define MOUNT_EVIL 70
#define MOUNT_NEUT 71

void spell_mount(char level, struct char_data *ch, struct char_data *victim,
		 struct obj_data *obj)
{
    struct char_data                       *m = NULL;
    int                                     mnr = 0;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

/* create a ridable mount, and automatically mount said creature */

    mnr = MOUNT_ONE;
    if (level < 30) {
	if (level < 12)
	    mnr++;
	if (level < 18)
	    mnr++;
	if (level < 24)
	    mnr++;
    } else {
	if (IS_EVIL(ch)) {
	    mnr = MOUNT_EVIL;
	} else if (IS_GOOD(ch)) {
	    mnr = MOUNT_GOOD;
	} else {
	    mnr = MOUNT_NEUT;
	}
    }

    m = read_mobile(mnr, VIRTUAL);
    if (m) {
	char_to_room(m, ch->in_room);
	act("In a flash of light, $N appears", FALSE, ch, 0, m, TO_CHAR);
	act("In a flash of light, $N appears, and $n hops on $s back", FALSE, ch, 0, m,
	    TO_ROOM);
	cprintf(ch, "You hop on your mount's back\r\n");
	MOUNTED(ch) = m;
	RIDDEN(m) = ch;
	GET_POS(ch) = POSITION_MOUNTED;
    } else {
	cprintf(ch, "horses aren't in database\r\n");
	return;
    }
}

void spell_dragon_ride(char level, struct char_data *ch, struct char_data *victim,
		       struct obj_data *obj)
{
    struct affected_type                    af;

    if (DEBUG > 1)
	log_info("called %s with %d, %s, %s, %s", __PRETTY_FUNCTION__, level, SAFE_NAME(ch),
		 SAFE_NAME(victim), SAFE_ONAME(obj));

    if (!ch)
	return;
    if (!((level >= 1) && (level <= ABS_MAX_LVL)))
	return;

    if (affected_by_spell(ch, SPELL_DRAGON_RIDE)) {
	cprintf(ch, "Already affected\r\n");
	return;
    }
    af.type = SPELL_DRAGON_RIDE;
    af.duration = level;
    af.modifier = 0;
    af.location = 0;
    af.bitvector = AFF_DRAGON_RIDE;
    affect_to_char(ch, &af);
}

#endif							       /* DRUID_WORKING */