diff --git a/src/include/spells.h b/src/include/spells.h
index 44281d0db..74b5773a3 100644
--- a/src/include/spells.h
+++ b/src/include/spells.h
@@ -235,6 +235,8 @@ typedef struct ConditionInfo {
 typedef struct {
     ConditionInfo *Condition;		/// Conditions to cast the spell.
     int Range;				/// Max range of the target.
+    /// Combat mode is when there are hostile non-coward units around
+    int Combat;				/// If it should be casted in combat
     /// FIXME: Add stuff here for target preference.
     /// FIXME: Heal units with the lowest hit points first.
 } AutoCastInfo;
diff --git a/src/stratagus/script_spell.cpp b/src/stratagus/script_spell.cpp
index 1f8aee882..0b203cabf 100644
--- a/src/stratagus/script_spell.cpp
+++ b/src/stratagus/script_spell.cpp
@@ -46,56 +46,17 @@
 #include "ccl_sound.h"
 #include "ccl.h"
 
-// **************************************************************************
-//		Direct affectation for spell
-// **************************************************************************
-
-/**
-**      Parse the dependency of spell.
-**      list = (upgrade "upgradename")
-*/
-local void ccl_spell_dependency(const char *id, SCM list, SpellType *spell)
-{
-    char *dependencyName;
-    SCM value;
-    int dependencyId;
-
-    DebugCheck(!id);
-    DebugCheck(!spell);
-
-    dependencyName = NULL;
-    dependencyId = -1;
-
-    value = gh_car(list);
-
-    if (!gh_eq_p(value, gh_symbol2scm("upgrade"))) {
-	return;
-    }
-    list = gh_cdr(list);
-    value = gh_car(list);
-
-    dependencyName = gh_scm2newstr(value, NULL);
-    dependencyId = UpgradeIdByIdent(dependencyName);
-    if (dependencyId == -1) {
-	// warn user
-	DebugLevel0Fn("Bad upgrade-name '%s'\n" _C_ dependencyName);
-	free(dependencyName);
-	return ;
-    }
-    spell->DependencyId = dependencyId;
-    free(dependencyName);
-}
-
-
 // **************************************************************************
 //		Action parsers for spellAction
 // **************************************************************************
 
-/**
+/*
 **	Parse the action for spell.
-**	list = (action-type lots-of-parameters).
+**
+**	@param list		SCM list object, with somthing like (action-type params).
+**	@param spellaction	Pointer to spellactopm.
 */
-local void CclParseSpellAction(SCM list, SpellType* spell, SpellActionType *spellaction)
+local void CclSpellAction(SCM list, SpellActionType *spellaction)
 {
     char* str;
     SCM	value = list;
@@ -324,6 +285,8 @@ local void CclParseSpellAction(SCM list, SpellType* spell, SpellActionType *spel
 **	@param 	value		scm value to convert.
 **
 **	@return CONDITION_TRUE, CONDITION_FALSE, CONDITION_ONLY or -1 on error.
+**	@note 	This is a helper function to make CclSpellCondition shorter
+**		and easier to understand.
 */
 local char Scm2Condition(SCM value)
 {
@@ -347,7 +310,7 @@ local char Scm2Condition(SCM value)
 **
 **	@notes: conditions must be allocated. All data already in is LOST.
 */
-local void CclSpellParseCondition(SCM list, ConditionInfo* condition)
+local void CclSpellCondition(SCM list, ConditionInfo* condition)
 {
     SCM value;
 
@@ -428,41 +391,40 @@ local void CclSpellParseCondition(SCM list, ConditionInfo* condition)
     }
 }
 
-/**
-**	FIXME: docu
+/*
+**	Parse the Condition for spell.
+**	
+**	@param list		SCM object to parse
+**	@param autocast		pointer to autocast to fill with data.
+**
+**	@notes: autocast must be allocated. All data already in is LOST.
 */
-local void ccl_spell_autocast(const char *id, SCM list, SpellType *spell)
+local void CclSpellAutocast(SCM list, AutoCastInfo* autocast)
 {
     SCM value;
-    int range;
 
-    DebugCheck(!id);
-    DebugCheck(!spell);
+    DebugCheck(!list);
+    DebugCheck(!autocast);
 
-    value = gh_car(list);
-    if (!gh_eq_p(value, gh_symbol2scm("range"))) {
-	return ;
+    while (!gh_null_p(list)) {
+	value = gh_car(list);
+	list = gh_cdr(list);
+	if (gh_eq_p(value,gh_symbol2scm("range"))) {
+	    autocast->Range=gh_scm2int(gh_car(list));
+	    list=gh_cdr(list);
+	} else if (gh_eq_p(value,gh_symbol2scm("combat"))) {
+	    autocast->Combat=Scm2Condition(gh_car(list));
+	    list=gh_cdr(list);
+	} else if (gh_eq_p(value,gh_symbol2scm("condition"))) {
+	    if (!autocast->Condition) {
+		autocast->Condition=(ConditionInfo*)malloc(sizeof(ConditionInfo));
+	    }
+	    CclSpellCondition(gh_car(list),autocast->Condition);
+	    list=gh_cdr(list);
+	} else {
+	    errl("Unsupported autocast tag",value);
+	}
     }
-
-    list = gh_cdr(list);
-    value = gh_car(list);
-    range = gh_scm2int(value);
-    if (range <= 0 && range != -1/*no limit*/) {
-	// Warn : range <= 0 have no sens, must be strict positive. or = -1
-	return ;
-    }
-    spell->AutoCast = malloc(sizeof(*spell->AutoCast));
-    memset(spell->AutoCast, 0, sizeof(*spell->AutoCast));
-    spell->AutoCast->Range = range;
-    list = gh_cdr(list);
-    value = gh_car(list);
-    if (!gh_eq_p(value, gh_symbol2scm("condition"))) {
-	return ;
-    }
-    list = gh_cdr(list);
-    value = gh_car(list);
-    spell->AutoCast->Condition=(ConditionInfo*)malloc(sizeof(ConditionInfo));
-    CclSpellParseCondition(value,spell->AutoCast->Condition);
 }
 
 /**
@@ -525,15 +487,23 @@ local SCM CclDefineSpell(SCM list)
 	    }
 	    list=gh_cdr(list);
 	} else if (gh_eq_p(value,gh_symbol2scm("action"))) {
-	    spell->Action=(SpellActionType*)malloc(sizeof(SpellActionType));
-	    CclParseSpellAction(gh_car(list),spell,spell->Action);
+	    if (!spell->Action) {
+		spell->Action=(SpellActionType*)malloc(sizeof(SpellActionType));
+	    }
+	    CclSpellAction(gh_car(list),spell->Action);
 	    list=gh_cdr(list);
 	} else if (gh_eq_p(value,gh_symbol2scm("condition"))) {
-	    spell->Conditions=(ConditionInfo*)malloc(sizeof(ConditionInfo));
-	    CclSpellParseCondition(gh_car(list),spell->Conditions);
+	    if (!spell->Conditions) {
+		spell->Conditions=(ConditionInfo*)malloc(sizeof(ConditionInfo));
+	    }
+	    CclSpellCondition(gh_car(list),spell->Conditions);
 	    list=gh_cdr(list);
 	} else if (gh_eq_p(value,gh_symbol2scm("autocast"))) {
-	    ccl_spell_autocast("autocast",gh_car(list),spell);
+	    if (!spell->AutoCast) {
+		spell->AutoCast=(AutoCastInfo*)malloc(sizeof(AutoCastInfo));
+		memset(spell->AutoCast,0,sizeof(AutoCastInfo*));
+	    }
+	    CclSpellAutocast(gh_car(list),spell->AutoCast);
 	    list=gh_cdr(list);
 	} else if (gh_eq_p(value,gh_symbol2scm("sound-when-cast"))) {
 	    //  Free the old name, get the new one
@@ -555,11 +525,15 @@ local SCM CclDefineSpell(SCM list)
 	    }
 	    free(str);
 	    list=gh_cdr(list);
-	} else if (gh_eq_p(value,gh_symbol2scm("depend"))) {
-	    ccl_spell_dependency("depend", gh_car(list), spell);
+	} else if (gh_eq_p(value,gh_symbol2scm("depend-upgrade"))) {
+	    str = gh_scm2newstr(gh_car(list), NULL);
+	    spell->DependencyId = UpgradeIdByIdent(str);
+	    free(str);
+	    if (spell->DependencyId == -1) {
+		errl("Bad upgrade name",gh_car(list));
+	    }
 	    list = gh_cdr(list);
-	} else 
-	{
+	} else {
 	    errl("Unsupported tag", value);
 	}
     }
@@ -591,18 +565,32 @@ local void SaveSpellCondition(CLFile *file,ConditionInfo* condition)
     DebugCheck(!file);
     DebugCheck(!condition);
 
-    CLprintf(file,"'( ");
+    CLprintf(file,"( ");
     //
     //	First save data related to flags.
     //	NOTE: (int) is there to keep compilers happy.
     //
-    CLprintf(file,"undead %s ",condstrings[(int)condition->Undead]);
-    CLprintf(file,"organic %s ",condstrings[(int)condition->Organic]);
-    CLprintf(file,"hero %s ",condstrings[(int)condition->Hero]);
-    CLprintf(file,"coward %s ",condstrings[(int)condition->Coward]);
-    CLprintf(file,"alliance %s ",condstrings[(int)condition->Alliance]);
-    CLprintf(file,"building %s ",condstrings[(int)condition->Building]);
-    CLprintf(file,"self %s ",condstrings[(int)condition->TargetSelf]);
+    if (condition->Undead!=CONDITION_TRUE) {
+	CLprintf(file,"undead %s ",condstrings[(int)condition->Undead]);
+    }
+    if (condition->Organic!=CONDITION_TRUE) {
+	CLprintf(file,"organic %s ",condstrings[(int)condition->Organic]);
+    }
+    if (condition->Hero!=CONDITION_TRUE) {
+	CLprintf(file,"hero %s ",condstrings[(int)condition->Hero]);
+    }
+    if (condition->Coward!=CONDITION_TRUE) {
+	CLprintf(file,"coward %s ",condstrings[(int)condition->Coward]);
+    }
+    if (condition->Alliance!=CONDITION_TRUE) {
+	CLprintf(file,"alliance %s ",condstrings[(int)condition->Alliance]);
+    }
+    if (condition->Building!=CONDITION_TRUE) {
+	CLprintf(file,"building %s ",condstrings[(int)condition->Building]);
+    }
+    if (condition->TargetSelf!=CONDITION_TRUE) {
+	CLprintf(file,"self %s ",condstrings[(int)condition->TargetSelf]);
+    }
     //
     //	Min/Max vital percents
     //
@@ -633,18 +621,18 @@ local void SaveSpellCondition(CLFile *file,ConditionInfo* condition)
 local void SaveSpellAction(CLFile *file,SpellActionType* action)
 {
     if (action->CastFunction==CastAreaBombardment) {
-	CLprintf(file," '(area-bombardment fields %d shards %d damage %d start-offset-x %d start-offset-y %d)",
+	CLprintf(file,"(area-bombardment fields %d shards %d damage %d start-offset-x %d start-offset-y %d)",
 		action->Data.AreaBombardment.Fields,
 		action->Data.AreaBombardment.Shards,
 		action->Data.AreaBombardment.Damage,
 		action->Data.AreaBombardment.StartOffsetX,
 		action->Data.AreaBombardment.StartOffsetY);
     } else if (action->CastFunction==CastFireball) {
-	CLprintf(file," '(fireball ttl %d damage %d)",
+	CLprintf(file,"(fireball ttl %d damage %d)",
 		action->Data.Fireball.TTL,
 		action->Data.Fireball.Damage);
     } else if (action->CastFunction==CastAdjustVitals) {
-	CLprintf(file," '(adjust-vitals");
+	CLprintf(file,"(adjust-vitals");
 	if (action->Data.AdjustVitals.HP) {
 	    CLprintf(file," hit-points %d",action->Data.AdjustVitals.HP);
 	}
@@ -656,11 +644,11 @@ local void SaveSpellAction(CLFile *file,SpellActionType* action)
 	}
 	CLprintf(file,")\n");
     } else if (action->CastFunction==CastSummon) {
-	CLprintf(file," '(summon unit-type %s time-to-live %d)",
+	CLprintf(file,"(summon unit-type %s time-to-live %d)",
 		action->Data.Summon.UnitType->Ident,
 		action->Data.Summon.TTL);
     } else if (action->CastFunction==CastAdjustBuffs) {
-	CLprintf(file," '(adjust-buffs");
+	CLprintf(file,"(adjust-buffs");
 	if (action->Data.AdjustBuffs.HasteTicks!=BUFF_NOT_AFFECTED) {
 	    CLprintf(file," haste-ticks %d",action->Data.AdjustBuffs.HasteTicks);
 	}
@@ -678,27 +666,27 @@ local void SaveSpellAction(CLFile *file,SpellActionType* action)
 	}
 	CLprintf(file,")");
     } else if (action->CastFunction==CastPolymorph) {
-	CLprintf(file," '(polymorph new-form %s)",
+	CLprintf(file,"(polymorph new-form %s)",
 		action->Data.Polymorph.NewForm->Ident);
     } else if (action->CastFunction==CastRaiseDead) {
-	CLprintf(file," '(raise-dead unit-raised %s time-to-live %d)",
+	CLprintf(file,"(raise-dead unit-raised %s time-to-live %d)",
 		action->Data.RaiseDead.UnitRaised->Ident,
 		action->Data.RaiseDead.TTL);
     } else if (action->CastFunction==CastFlameShield) {
-	CLprintf(file," '(flame-shield duration %d)",
+	CLprintf(file,"(flame-shield duration %d)",
 		action->Data.FlameShield.TTL);
     } else if (action->CastFunction==CastRunes) {
-	CLprintf(file," '(runes ttl %d damage %d)",
+	CLprintf(file,"(runes ttl %d damage %d)",
 		action->Data.Runes.TTL,
 		action->Data.Runes.Damage);
     } else if (action->CastFunction==CastSpawnPortal) {
-	CLprintf(file," '(spawn-portal portal-type %s)",
+	CLprintf(file,"(spawn-portal portal-type %s)",
 		action->Data.SpawnPortal.PortalType->Ident);
     } else if (action->CastFunction==CastDeathCoil) {
-	CLprintf(file," '(death-coil)");
+	CLprintf(file,"(death-coil)");
 	// FIXME: more?
     } else if (action->CastFunction==CastWhirlwind) {
-	CLprintf(file," '(whirlwind duration %d)",
+	CLprintf(file,"(whirlwind duration %d)",
 		action->Data.Whirlwind.TTL);
 	// FIXME: more?
     } 
@@ -754,20 +742,25 @@ global void SaveSpells(CLFile *file)
 	//
 	//  Save the action(effect of the spell)
 	//
-	CLprintf(file,"    'action ");
+	CLprintf(file,"    'action '");
 	SaveSpellAction(file,spell->Action);
 	CLprintf(file,"\n");
 	//
 	//  FIXME: Save conditions
 	//
 	if (spell->Conditions) {
-	    CLprintf(file,"    'condition ");
+	    CLprintf(file,"    'condition '");
 	    SaveSpellCondition(file,spell->Conditions);
 	    CLprintf(file,"\n");
 	}
 	//
 	//  FIXME: Save autocast and AI info
 	//
+	if (spell->AutoCast) {
+	    CLprintf(file,"    'autocast '(range %d condition ",spell->AutoCast->Range);
+	    SaveSpellCondition(file,spell->Conditions);
+	    CLprintf(file,")\n");
+	}
 	CLprintf(file,")\n");
     }
 }
diff --git a/src/stratagus/spells.cpp b/src/stratagus/spells.cpp
index 7f2d8796a..1a45fd3b4 100644
--- a/src/stratagus/spells.cpp
+++ b/src/stratagus/spells.cpp
@@ -706,7 +706,7 @@ global int CastAdjustBuffs(Unit *caster, const SpellType *spell, Unit *target,
     // get mana cost
     caster->Mana -= spell->ManaCost;
 
-    if (spell->Action->Data.AdjustBuffs.SlowTicks!=BUFF_NOT_AFFECTED) {
+    if (spell->Action->Data.AdjustBuffs.HasteTicks!=BUFF_NOT_AFFECTED) {
 	target->Haste=spell->Action->Data.AdjustBuffs.HasteTicks;
     }
     if (spell->Action->Data.AdjustBuffs.SlowTicks!=BUFF_NOT_AFFECTED) {
@@ -790,7 +790,7 @@ global int CastAdjustVitals(Unit *caster, const SpellType *spell, Unit *target,
 
     DebugCheck(castcount<0);
 
-    DebugLevel0Fn("Used to have %d hp and %d mana.\n" _C_ target->HP _C_ target->Mana);
+    DebugLevel3Fn("Used to have %d hp and %d mana.\n" _C_ target->HP _C_ target->Mana);
 
     caster->Mana-=castcount*manacost;
     if (hp < 0) {
@@ -809,7 +809,7 @@ global int CastAdjustVitals(Unit *caster, const SpellType *spell, Unit *target,
 	target->Mana=target->Type->_MaxMana;
     }
 
-    DebugLevel0Fn("Unit now has %d hp and %d mana.\n" _C_ target->HP _C_ target->Mana);
+    DebugLevel3Fn("Unit now has %d hp and %d mana.\n" _C_ target->HP _C_ target->Mana);
     PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
     MakeMissile(spell->Missile,
 	    x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
@@ -1185,7 +1185,7 @@ local int PassCondition(const Unit* caster,const SpellType* spell,const Unit* ta
 	    }
 	}
 	if (condition->Alliance!=CONDITION_TRUE) {
-	    if ((condition->Alliance==CONDITION_ONLY)^(IsAllied(caster->Player,target))) {
+	    if ((condition->Alliance==CONDITION_ONLY)^(IsAllied(caster->Player,target)||target->Player==caster->Player)) {
 		return 0;
 	    }
 	}
@@ -1197,20 +1197,40 @@ local int PassCondition(const Unit* caster,const SpellType* spell,const Unit* ta
 	//
 	//	Check vitals now.
 	//
-	if (condition->MinHpPercent*target->Stats->HitPoints>target->HP) {
+	if (condition->MinHpPercent*target->Stats->HitPoints/100>target->HP) {
 	    return 0;
 	}
-	if (condition->MaxHpPercent*target->Stats->HitPoints<target->HP) {
+	if (condition->MaxHpPercent*target->Stats->HitPoints/100<=target->HP) {
 	    return 0;
 	}
 	if (target->Type->CanCastSpell) {
-	    if (condition->MinManaPercent*target->Type->_MaxMana>target->Mana) {
+	    if (condition->MinManaPercent*target->Type->_MaxMana/100>target->Mana) {
 		return 0;
 	    }
-	    if (condition->MaxManaPercent*target->Type->_MaxMana<target->Mana) {
+	    if (condition->MaxManaPercent*target->Type->_MaxMana/100<target->Mana) {
 		return 0;
 	    }
 	}
+	//
+	//	Check for slow/haste stuff
+	//	This should be used mostly for ai, if you want to keep casting
+	//	slow to no effect I can't see why should we stop you.
+	//
+	if (condition->MaxSlowTicks<target->Slow) {
+	    return 0;
+	}
+	if (condition->MaxHasteTicks<target->Haste) {
+	    return 0;
+	}
+	if (condition->MaxBloodlustTicks<target->Bloodlust) {
+	    return 0;
+	}
+	if (condition->MaxInvisibilityTicks<target->Invisible) {
+	    return 0;
+	}
+	if (condition->MaxInvincibilityTicks<target->UnholyArmor) {
+	    return 0;
+	}
     }
     return 1;
 }
@@ -1231,59 +1251,98 @@ local Target *SelectTargetUnitsOfAutoCast(const Unit *caster, const SpellType *s
     int x;
     int y;
     int range;
-    int nb_units;
+    int nunits;
     int i;
     int j;
+    int combat;
 
     DebugCheck(!spell);
     DebugCheck(!spell->AutoCast);
     DebugCheck(!caster);
 
+    x=caster->X;
+    y=caster->Y;
+    range=spell->AutoCast->Range;
+
+    //
+    //	Select all units aroung the caster
+    //
+    nunits = SelectUnits(caster->X - range, caster->Y - range,
+	    caster->X + range + caster->Type->TileWidth, caster->Y + range + caster->Type->TileHeight, table);
+    //
+    //  Check every unit if it is hostile
+    // 
+    combat=0;
+    for (i = 0; i < nunits; i++) {
+	if (IsEnemy(caster->Player,table[i]) && !table[i]->Type->Coward) {
+	    combat=1;
+	}
+    }
+
+    //
+    //	Check generic conditions. FIXME: a better way to do this?
+    //
+    if (spell->AutoCast->Combat!=CONDITION_TRUE) {
+	if ((spell->AutoCast->Combat==CONDITION_ONLY)^(combat)) {
+	    return 0;
+	}
+    }
+
     switch (spell->Target) {
-	case TargetSelf :
-	    return NewTargetUnit(caster);
 	case TargetNone :
+	    // TargetNone?
 	    return NewTargetNone();
+	case TargetSelf :
+	    if (PassCondition(caster, spell, caster, x, y, spell->Conditions) &&
+		    PassCondition(caster, spell, caster, x, y, spell->AutoCast->Condition)) {
+    	        return NewTargetUnit(caster);
+    	    }
+	    return 0;
 	case TargetPosition:
-	    range = spell->AutoCast->Range;
-	    do {
-		x = caster->X + SyncRand() % (2 * range) - range;
-		y = caster->Y + SyncRand() % (2 * range) - range;
-	    } while (x < 0 && x <= TheMap.Width
-			    && y < 0 && y <= TheMap.Height);
-	    
-	    // FIXME : CHOOSE a better POSITION (add info in structure ???)
-	    // Just good enough for holyvision...
-	    return NewTargetPosition(x, y);
+	    return 0;
+	    //  Autocast with a position? That's hard
+	    //  Possibilities: cast reveal-map on a dark region
+	    //  Cast raise dead on a bunch of corpses. That would rule.
+	    //  Cast summon until out of mana in the heat of battle. Trivial?
+	    //  Find a tight group of units and cast area-damage spells. HARD,
+	    //  but it is a must-have for AI. What about area-heal?
 	case TargetUnit:
-	    x=caster->X;
-	    y=caster->Y;
-	    range=spell->AutoCast->Range;
-	    // ( + 1) would be ( + caster->size) ??
-	    nb_units = SelectUnits(caster->X - range, caster->Y - range,
-		caster->X + range + 1, caster->Y + range + 1,table);
-	    // For all Unit, check if it is a possible target
-	    for (i = 0, j = 0; i < nb_units; i++) {
-		if (PassCondition(caster,spell,table[i],x,y,spell->Conditions)) {
-			table[j++] = table[i];
+	    //
+	    //	The units are already selected.
+	    //  Check every unit if it is a possible target
+	    // 
+	    for (i = 0, j = 0; i < nunits; i++) {
+		//  FIXME: autocast conditions should include normal conditions.
+		//  FIXME: no, really, they should.
+		if (PassCondition(caster, spell, table[i], x, y, spell->Conditions) &&
+			PassCondition(caster, spell, table[i], x, y, spell->AutoCast->Condition)) {
+		    table[j++] = table[i];
 		}
 	    }
-	    nb_units = j;
-	    if (nb_units != 0) {
+	    nunits = j;
+	    //	
+	    //	Now select the best unit to target.
+	    //	FIXME: Some really smart way to do this. 
+	    //	FIXME: Heal the unit with the lowest hit-points
+	    //	FIXME: Bloodlust the unit with the highest hit-point
+	    //	FIMXE: it will survive more
+	    //
+	    if (nunits != 0) {
 #if 0
-// For the best target
+		// For the best target???
 		sort(table, nb_units, spell->autocast->f_order);
 		return NewTargetUnit(table[0]);
 #else
-// For a random valid target
-		i = SyncRand() % nb_units;
+		//	Best unit, random unit, oh well, same stuff.
+		i = SyncRand() % nunits;
 		return NewTargetUnit(table[i]);
 #endif
 	    }
 	    break;
 	default:
-	    // Error : add the new cases
-	    // FIXME : Warn developpers
+	    // Something is wrong
+	    DebugLevel0Fn("Spell is screwed up, unknown target type\n");
+	    DebugCheck(1);
 	    return NULL;
 	    break;
 	}
@@ -1473,9 +1532,10 @@ global int AutoCastSpell(Unit *caster, const SpellType *spell)
 
     target = NULL;
 
-/*    if (PassCondition(caster,spell,target,x,y,spell->Conditions))
+    //  Check for mana, trivial optimization.
+    if (caster->Mana<spell->ManaCost) {
 	return 0;
-    }*/
+    }
     target = SelectTargetUnitsOfAutoCast(caster, spell);
     if (target == NULL) {
 	return 0;