using System;
using System.Drawing;
using System.Collections;
using System.IO;
[assembly: OrganismClass("MyCreature")]
[assembly: AuthorInformation("naka", "")]
[AnimalSkin(AnimalSkinFamilyEnum.Beetle,"mari")]
[CarnivoreAttribute(true)]
[MatureSize(26)]
[MaximumEnergyPoints( 15 )]
[EatingSpeedPoints( 5 )]
[AttackDamagePoints( 0 )]
[DefendDamagePoints( 0 )]
[MaximumSpeedPoints( 20 )]
[CamouflagePoints( 0 )]
[EyesightPoints( 60 )]
/* NOX
[AnimalSkin(AnimalSkinFamilyEnum.Beetle,"XXE40240805")]
[MatureSize(32)]
[MaximumEnergyPoints( 18 )]
[EatingSpeedPoints( 5 )]
[AttackDamagePoints( 20 )]
[DefendDamagePoints( 0 )]
[MaximumSpeedPoints( 17 )]
[CamouflagePoints( 0 )]
[EyesightPoints( 40 )]
*/
public class MyCreature : Animal
{
private class DistComparer3 : IComparer {
MyCreature my;
public DistComparer3(MyCreature my) {
this.my = my;
}
public int Compare(object a,object b) {
if(a==null || b ==null)
return 0;
int d = my.CellDistanceTo(((OrganismState)a))
- my.CellDistanceTo(((OrganismState) b));
if(d == 0 && a is AnimalState && b is AnimalState){
d=Power((AnimalState)b)-Power((AnimalState)a);
}
if(d == 0 && a is AnimalState && b is AnimalState){
d=((AnimalState)a).Damage-((AnimalState)b).Damage;
}
return d;
}
int Power (AnimalState a){
return a.AnimalSpecies.MaximumAttackDamagePerUnitRadius * a.Radius
+a.AnimalSpecies.MaximumDefendDamagePerUnitRadius * a.Radius;
}
}
/*
private class SortableOrganism: IComparable
{
public OrganismState organism;
public double score;
public SortableOrganism(OrganismState organism, double score)
{
this.organism = organism;
this.score = score;
}
public virtual int CompareTo(object obj)
{
if (((SortableOrganism) obj).score < score)
return (-1);
if (((SortableOrganism) obj).score == score)
return 0;
else
return 1;
}
}
*/
Hashtable Creatures = new Hashtable();
public ArrayList kyoi = new ArrayList();
public ArrayList kamo = new ArrayList();
public ArrayList animal = new ArrayList();
public ArrayList esa = new ArrayList();
public ArrayList esa2 = new ArrayList();
public ArrayList Plants = new ArrayList();
public ArrayList Friends = new ArrayList();
public ArrayList Dead = new ArrayList();
public ArrayList AttackAS = new ArrayList();
public ArrayList FoundAS = new ArrayList();
public ArrayList AS = new ArrayList();
public Vector lastRunaway;
public bool isBlocked;
Hashtable SeenCreatures = new Hashtable();
public ArrayList Seenkyoi =new ArrayList();
private ArrayList RetiredFriends = new ArrayList();
public ArrayList SeenCarnivores = new ArrayList();
private bool isCarnivoreNear = false;
ArrayList Attackers = new ArrayList();
bool isclose;
bool isfood;
UtilMap map;
private class SeenCreature
{
public SeenCreature(OrganismState creature, int tick)
{
this.creature = creature;
this.tick = tick;
}
public OrganismState creature;
public int tick;
}
protected override void Initialize()
{
map = new UtilMap(this);
Load += new LoadEventHandler(LoadEvent);
Idle += new IdleEventHandler(IdleEvent);
Attacked += new AttackedEventHandler(AttackedEvent);
}
void LoadEvent(object sender, LoadEventArgs e)
{
kyoi.Clear();
kamo.Clear();
esa.Clear();
esa2.Clear();
Attackers.Clear();
animal.Clear();
Plants.Clear();
Friends.Clear();
Dead.Clear();
SeenCarnivores.Clear();
RetiredFriends.Clear();
isBlocked=false;
FoundAS.Clear();
AS.Clear();
AttackAS.Clear();
isclose = false;
isfood = false;
isCarnivoreNear = false;
if(OldAge())
MyAntenna = Antenna.OldAge;
else
MyAntenna = Antenna.None;
/*NOX
if (State.Generation > 300)
{
if (((State.TickAge + 1) % 2) == 0)
{
Antennas.RightAntenna = (AntennaPosition)(((State.TickAge + 1) * 83) % 10);
}
else
Antennas.RightAntenna = (AntennaPosition)(((State.TickAge + 1) * 58) % 10);
}
else
Antennas.RightAntenna = (AntennaPosition)(((State.TickAge + 1) * 83) % 10);
NOX */
}
Point GetBypass(OrganismState target) {
int dx = target.GridX - State.GridX;
int dy = target.GridY - State.GridY;
int size = State.CellRadius + target.CellRadius + 1;
if(Math.Abs(dx) > Math.Abs(dy)) {
if(OrganismRandom.Next(2) == 1) {
return new Point(Position.X,(target.GridY + size) * 8);
} else {
return new Point(Position.X,(target.GridY - size) * 8);
}
} else {
if(OrganismRandom.Next(2) == 1) {
return new Point((target.GridX + size) * 8,Position.Y);
} else {
return new Point((target.GridX - size) * 8,Position.Y);
}
}
}
void IdleEvent(object sender, IdleEventArgs e)
{
if(CanReproduce){
BeginReproduction(null);
}
ScanAll();
MakeMap();
if(OldAge()&&Friends.Count > 0)
{
Attack();
Defend();
if(AS.Count>0)
map.findingFood(AS);
else
if(AttackAS.Count>0)
{
if(!isclose)
map.findingFood(AttackAS);
else
StopMoving();
}
else if(FoundAS.Count>0){
if(!isclose)
map.findingFood(FoundAS);
else
StopMoving();
}else if(!map.chaseenemy(Friends,Species.MaximumSpeed))
{
map.ResetCost();
}
}
else{
Eat();
Attack();
Defend();
if(Dead.Count > 0 && !isCarnivoreNear && !isfood){
MyAntenna = Antenna.None;
if(!map.findingFood(Dead))
{
map.ResetCost();
}
}
else if (State.StoredEnergy<50)
{
TryWalk();
MyAntenna = Antenna.None;
}
else if((kamo.Count==0||kyoi.Count>0)&&AS.Count>0)
map.chaseenemy(AS,Species.MaximumSpeed);
else if((kamo.Count==0||kyoi.Count>0)&&AttackAS.Count>0)
{
if(!isclose)
map.chaseenemy(AttackAS,8);
else
StopMoving();
}
else if((kamo.Count==0||kyoi.Count>0)&&FoundAS.Count>0){
if(!isclose)
map.chaseenemy(FoundAS,8);
else
StopMoving();
}
else if(kyoi.Count>0 || SeenCarnivores.Count > 0){
if(Friends.Count>0&&CellDistanceTo((OrganismState)Friends[0])<4)
StopMoving();
else
map.runawayFromEnemy(kyoi);
}
else if(kamo.Count>0){
MyAntenna = Antenna.None;
AnimalState best = (AnimalState) kamo[0];
int dist=CellDistanceTo(best);
int speed = 12;
if(dist<4)
speed=Species.MaximumSpeed;
else if(best.CurrentMoveToAction != null)
speed = Math.Max(12,Math.Min(Species.MaximumSpeed,best.CurrentMoveToAction.MovementVector.Speed+1));
else
speed=12;
if(!map.chaseenemy(kamo,speed))
{
map.ResetCost();
}
}
else if(esa2.Count>0){
AnimalState best = (AnimalState) esa2[0];
int dist=CellDistanceTo(best);
int speed = 3;
if(dist<2)
speed = Species.MaximumSpeed;
if(State.PercentInjured <0.5&&(State.PercentEnergy<0.4||dist<3))
map.chaseenemy(esa2,speed);
}
else if(esa.Count > 0){
AnimalState best = esa[0] as AnimalState;
int dist=CellDistanceTo(best);
StopMoving();
/*
if(Friends.Count ==0)
{
StopMoving();
}
else {
int speed = 3;
if(!map.chaseenemy(esa,speed))
{
map.ResetCost();
}
}
*/
}
else
TryWalk();
}
if(OldAge())
MyAntenna = Antenna.OldAge;
}
void Attack(){
if(kyoi.Count>0){
AnimalState closestCarni =(AnimalState)kyoi[0];
if(WithinAttackingRange(closestCarni))
{
try
{
BeginAttacking(closestCarni);
return;
}
catch(Exception ex)
{
WriteTrace(ex.ToString());
}
}
}
if(animal.Count>0){
AnimalState a = (AnimalState)animal[0];
if (CellDistanceTo(a)<5)
if (a.AnimalSpecies.IsCarnivore|| a.EnergyState == EnergyState.Hungry
|| a.EnergyState == EnergyState.Deterioration||CanWin(a,1))
try{
BeginAttacking(a);
return;
}
catch {};
}
if(RetiredFriends.Count>0){
AnimalState a = (AnimalState)RetiredFriends[0];
if (CellDistanceTo(a)<5)
try{
BeginAttacking(a);
return;
}
catch {};
}
}
void Defend(){
if(kyoi.Count>0){
AnimalState closestCarni =(AnimalState)kyoi[0];
if(WithinAttackingRange(closestCarni))
{
try
{
BeginDefending(closestCarni);
return;
}
catch(Exception ex)
{
WriteTrace(ex.ToString());
}
}
}
try{
AnimalState a = (AnimalState)animal[0];
BeginDefending(a);
}
catch{};
}
public bool IsMyFriend(AnimalState animalState){
/*
if (animalState.Species.Skin ==null)
return false;
bool ret = false;
ret=!animalState.AnimalSpecies.IsCarnivore &&
(animalState.Species.Skin.StartsWith("mary"));
ret = ret && animalState.AnimalSpecies.SkinFamily == AnimalSkinFamilyEnum.Beetle;
return ret;
*/
/* if (animalState.Species.Skin ==null)
return false;
bool ret = false;
ret=!animalState.AnimalSpecies.IsCarnivore &&
( animalState.AnimalSpecies.LifeSpan == 600 ) &&
( animalState.AnimalSpecies.MaximumEnergyPerUnitRadius == 443 ) &&
( animalState.AnimalSpecies.EatingSpeedPerUnitRadius == 2 ) &&
( animalState.AnimalSpecies.MaximumAttackDamagePerUnitRadius == 50 ) &&
( animalState.AnimalSpecies.MaximumDefendDamagePerUnitRadius == 52 ) &&
( animalState.AnimalSpecies.MaximumSpeed == 45 ) &&
( animalState.AnimalSpecies.EyesightRadius == 6 )
&&(animalState.Species.Skin.StartsWith("mary"));
ret = ret && animalState.AnimalSpecies.SkinFamily == AnimalSkinFamilyEnum.Spider;
return ret;
*/
/*
bool ret = false;
ret=!animalState.AnimalSpecies.IsCarnivore &&
ret = ret && animalState.AnimalSpecies.SkinFamily == AnimalSkinFamilyEnum.Spider;
return ret;
*/
if (animalState.Species.Skin ==null||!animalState.Species.Skin.StartsWith("mari"))
return false;
if(!animalState.AnimalSpecies.IsCarnivore &&animalState.AnimalSpecies.MatureRadius == 24&&animalState.Antennas.LeftAntenna==(AntennaPosition)(((animalState.TickAge) * 33 ) % 10))
return true;
return false;
}
/* public bool IsMyFriend(AnimalState animalState){
if (animalState.Species.Skin ==null)
return false;
bool ret = false;
ret=!animalState.AnimalSpecies.IsCarnivore &&
( animalState.AnimalSpecies.LifeSpan == 600 ) &&
( animalState.AnimalSpecies.EatingSpeedPerUnitRadius == 4 ) &&
( animalState.AnimalSpecies.MaximumAttackDamagePerUnitRadius == 52 ) &&
( animalState.AnimalSpecies.MaximumDefendDamagePerUnitRadius == 57 ) &&
( animalState.AnimalSpecies.MaximumSpeed == 30 ) &&
( animalState.AnimalSpecies.EyesightRadius == 6 )
&&(animalState.Species.Skin.StartsWith("mary"));
ret = ret && animalState.AnimalSpecies.SkinFamily == AnimalSkinFamilyEnum.Ant;
return ret;
}
*/
public Point GetRandPos(){
Point p;
do
{
int d = (State.CellRadius+1)<<3;
int x = OrganismRandom.Next(d, WorldWidth-d-1);
int y = OrganismRandom.Next(d, WorldHeight-d-1);
p = new Point(x,y);
}while( p==Position );
return p;
}
void MoveCompletedEvent(object o, MoveCompletedEventArgs e)
{
if( e.Reason == ReasonForStop.Blocked &&e.BlockingOrganism !=null&&e.BlockingOrganism is PlantState)
isBlocked=true;
}
void TryWalk()
{
if(lastRunaway == null)
{
lastRunaway =Vector.Subtract(Position,GetRandPos());
}
map.randomwalk(lastRunaway);
}
void Eat()
{
if( CanEat )
{
foreach( OrganismState o in Dead )
{
try{
BeginEating( o );
return;
}catch{};
}
}
}
public int CellDistanceTo(OrganismState creature)
{
return Math.Max(Math.Abs(State.GridX - creature.GridX),
Math.Abs(State.GridY - creature.GridY)) - State.CellRadius - creature.CellRadius - 1;
}
public int CellDistanceTo(OrganismState creature1,OrganismState creature2)
{
return Math.Max(Math.Abs(creature1.GridX - creature2.GridX),
Math.Abs(creature1.GridY - creature2.GridY)) - creature1.CellRadius - creature2.CellRadius - 1;
}
Point GetGrid( Point p ){
return new Point( p.X>>3 , p.Y>>3 );
}
bool OldAge()
{
if(State.ReproductionWait > Species.LifeSpan - State.TickAge)
return true;
if(State.Species.GrowthWait*(State.Species.MatureRadius - State.Radius)> Species.LifeSpan - State.TickAge)
return true;
return false;
}
bool OldAge(AnimalState a)
{
if(a.ReproductionWait > a.Species.LifeSpan - a.TickAge)
return true;
if(a.Species.GrowthWait*(a.Species.MatureRadius - a.Radius)> a.Species.LifeSpan - a.TickAge)
return true;
return false;
}
void AttackedEvent (object sender, AttackedEventArgs e)
{
Attackers.Add(e.Attacker);
}
private void ScanAll()
{
Hashtable tmp1 = new Hashtable() ;
for( int i = 0 ; i < 3 ; i++ ){
ArrayList tmp = Scan();
foreach (OrganismState creature in tmp)
{
if(tmp1.ContainsKey(creature.ID))
tmp1.Remove(creature.ID);
tmp1.Add(creature.ID,creature);
}
}
ArrayList tmp2= new ArrayList();
foreach(OrganismState creature in Creatures.Values) {
if(creature == null )
continue;
if(tmp1.ContainsKey(creature.ID))
tmp2.Add(creature.ID);
else
{
int j = 1;
AnimalState an = creature as AnimalState;
if(an != null &&an.AnimalSpecies.InvisibleOdds >0)
j = 10;
OrganismState org = null ;
int i = 0;
do{
org = RefreshState(creature.ID);
if(org != null && !tmp1.ContainsKey(creature.ID))
tmp1.Add(creature.ID,org);
i++;
}
while( i < j && org == null);
if(org ==null && !tmp2.Contains(creature.ID))
tmp2.Add(creature.ID);
}
}
foreach(String str in tmp2){
if(SeenCreatures.ContainsKey(str))
SeenCreatures.Remove(str);
if(Creatures[str] != null&&((OrganismState)Creatures[str]).IsAlive)
SeenCreatures.Add(str,new SeenCreature((OrganismState) Creatures[str], State.TickAge));
}
Creatures = tmp1;
foreach(OrganismState org in Attackers)
if(!Creatures.ContainsKey(org.ID))
Creatures.Add(org.ID,org);
foreach(OrganismState org in Creatures.Values) {
if(org == null )
continue;
if(SeenCreatures.ContainsKey(org.ID))
SeenCreatures.Remove(org.ID);
if(org is PlantState){
Plants.Add(org);
if(CellDistanceTo(org)<=Species.MaximumSpeed>>3+1)
isBlocked=true;
}
else {
if(!((AnimalState)org).IsAlive)
Dead.Add(org);
else
if(IsMySpecies((AnimalState)org)){
if(AnimalAntenna((AnimalState)org)==Antenna.FoundAS){
if(CellDistanceTo(org)==0)
isclose=true;
FoundAS.Add(org);
}
if(AnimalAntenna((AnimalState)org)==Antenna.AttackAS){
if(CellDistanceTo(org)==0)
isclose=true;
AttackAS.Add(org);
}
if(AnimalAntenna((AnimalState)org)==Antenna.OldAge)
RetiredFriends.Add(org);
else {
if(CellDistanceTo(org)<=Species.MaximumSpeed>>3+1)
isBlocked=true;
Friends.Add(org);
}
}
else {
animal.Add(org);
if(((AnimalState)org).AnimalSpecies.IsCarnivore){
if(CanWin((AnimalState) org,0.8 ))
kamo.Add(org);
else {
if(CellDistanceTo(org)<2 )
MyAntenna = Antenna.AttackAS;
else
MyAntenna = Antenna.FoundAS;
if(!CanWin((AnimalState) org,1.1)){
AS.Add(org);
kyoi.Add(org);
if(CellDistanceTo(org)<5)
isCarnivoreNear=true;
}
}
}
else if(IsMyFriend((AnimalState)org))
{
if(!OldAge((AnimalState)org))
animal.Remove(org);
esa.Add(org);
}
else {
if(!CanWin((AnimalState) org,1.1))
{
}
else
esa2.Add(org);
}
}
}
}
/* if(AttackAS.Count>0 && AS.Count == 0){
if(OldAge())
MyAntenna = Antenna.OldAge;
else
MyAntenna = Antenna.None;
}
*/
ArrayList keys = new ArrayList();
foreach(String str in SeenCreatures.Keys){
if(SeenCreatures[str] == null)
continue;
int tick = 7;
AnimalState an2 = Creatures[str] as AnimalState;
if(an2 != null &&an2.AnimalSpecies.InvisibleOdds >0)
tick = 15;
if (this.State.TickAge - ((SeenCreature) SeenCreatures[str]).tick > tick)
keys.Add(str);
else
{
AnimalState an = ((SeenCreature) SeenCreatures[str]).creature as AnimalState;
if(an != null
&&an.IsAlive
&&an.AnimalSpecies.IsCarnivore
&&!CanWin(an,1.1))
SeenCarnivores.Add(an.Position);
}
}
foreach(String str in keys)
SeenCreatures.Remove(str);
DistComparer3 dc =new DistComparer3(this);
if(Attackers.Count>1)
foreach(OrganismState os in Attackers){
if(!kyoi.Contains(os))
kyoi.Add(os);
if(!SeenCarnivores.Contains(os.Position))
SeenCarnivores.Add(os.Position);
}
kyoi.Sort(dc);
kamo.Sort(dc);
esa.Sort(dc);
esa2.Sort(dc);
animal.Sort(dc);
RetiredFriends.Sort(dc);
Plants.Sort(dc);
Friends.Sort(dc);
Dead.Sort(dc);
ArrayList tmp3 = new ArrayList();
AS.Sort(dc);
foreach(AnimalState as1 in AS)
{
int best = CellDistanceTo((OrganismState)AS[0]);
foreach(AnimalState as2 in AttackAS)
{
int dist = CellDistanceTo(as1,as2);
if( dist<5&&dist<=best&&!tmp3.Contains(as1))
tmp3.Add(as1);
}
foreach(AnimalState as2 in FoundAS)
{
int dist = CellDistanceTo(as1,as2);
if( dist<5&&dist<=best&&!tmp3.Contains(as1))
tmp3.Add(as1);
}
}
AS = tmp3;
if(Dead.Count>0 && kyoi.Count>0)
foreach(AnimalState as1 in Dead)
{
int best = 100;
foreach(AnimalState as2 in kyoi)
{
if(!as2.AnimalSpecies.IsCarnivore)
continue;
int dist = CellDistanceTo(as1,as2);
if(best > dist)
best = dist;
}
if(best < CellDistanceTo(as1))
isfood = true;
}
}
private double LeftTicks(AnimalState d,AnimalState a) {
double dHitpoint = EngineSettings.DamageToKillPerUnitOfRadius * d.Radius - d.Damage;
double aAttackpoint = a.AnimalSpecies.MaximumAttackDamagePerUnitRadius * a.Radius;
double dDefendpoint = d.AnimalSpecies.MaximumDefendDamagePerUnitRadius * d.Radius;
return dHitpoint / Math.Max(1,aAttackpoint - dDefendpoint + 500);
}
private bool CanWin(AnimalState target,double canWinAlpha) {
if(target == null) return false;
return canWinAlpha*LeftTicks(State,target) > LeftTicks(target,State);
}
/*
private bool CanWin(AnimalState defender,double canWinAlpha) {
double attackerAttackDefend = (State.AnimalSpecies.MaximumAttackDamagePerUnitRadius+State.AnimalSpecies.MaximumDefendDamagePerUnitRadius)*State.Radius;
double defenderAttackDefend = (defender.AnimalSpecies.MaximumAttackDamagePerUnitRadius+defender.AnimalSpecies.MaximumDefendDamagePerUnitRadius)*defender.Radius;
double attackerCanLoose = EngineSettings.DamageToKillPerUnitOfRadius*State.Radius-State.Damage;
double defenderCanLoose = EngineSettings.DamageToKillPerUnitOfRadius*defender.Radius-defender.Damage;
if(defenderCanLoose<0) defenderCanLoose=0.01;
if(attackerCanLoose<0) attackerCanLoose=0.01;
return ((attackerCanLoose*attackerAttackDefend) / (defenderCanLoose*defenderAttackDefend) > canWinAlpha);
}
public double CanWin(AnimalState defender)
{
double attackerCanLoose = EngineSettings.DamageToKillPerUnitOfRadius*State.Radius-State.Damage;
double defenderCanLoose = EngineSettings.DamageToKillPerUnitOfRadius*defender.Radius-defender.Damage;
if(defenderCanLoose<0) defenderCanLoose=0.01;
if(attackerCanLoose<0) attackerCanLoose=0.01;
double attackerAttackDefend = (State.AnimalSpecies.MaximumAttackDamagePerUnitRadius+State.AnimalSpecies.MaximumDefendDamagePerUnitRadius)*State.Radius;
double defenderAttackDefend = (defender.AnimalSpecies.MaximumAttackDamagePerUnitRadius+defender.AnimalSpecies.MaximumDefendDamagePerUnitRadius)*defender.Radius;
return ((attackerCanLoose*attackerAttackDefend) / (defenderCanLoose*defenderAttackDefend));
}
*/
private void MakeMap()
{
map.Update();
}
public OrganismState ClosestCreature(ArrayList array)
{
if ((array == null) || (array.Count == 0))
return null;
OrganismState bestCreature = (OrganismState) array[0];
foreach (OrganismState creature in array)
if (DistanceTo(creature) < DistanceTo(bestCreature))
bestCreature = creature;
return bestCreature;
}
private Antenna MyAntenna
{
get
{
return (Antenna) this.Antennas.LeftAntenna;
}
set
{
this.Antennas.LeftAntenna = (AntennaPosition) value;
}
}
private Antenna AnimalAntenna(AnimalState animal)
{
return (Antenna) animal.Antennas.LeftAntenna;
}
private enum Antenna
{
None = AntennaPosition.Bottom,
OldAge = AntennaPosition.Backward,
FoundAS = AntennaPosition.Left,
AttackAS = AntennaPosition.BottomLeft
}
public override void SerializeAnimal(MemoryStream m)
{
}
public override void DeserializeAnimal(MemoryStream m)
{
}
}
public class UtilMap
{
private class DistComparer : IComparer {
Vector v;
public DistComparer(Vector v) {
this.v =v;
}
public int Compare(object a,object b) {
if(a==null || b ==null)
return 0;
Vector va = Vector.Subtract(new Point(0,0),(Point)a);
Vector vb = Vector.Subtract(new Point(0,0),(Point)b);
va = va.GetUnitVector();
vb = vb.GetUnitVector();
double da = v.X*va.X+v.Y*va.Y;
double db = v.X*vb.X+v.Y*vb.Y;
return((int)(db - da));
}
}
private class DistComparer2 : IComparer {
ArrayList enemies;
Point myPoint;
Animal my;
public DistComparer2(ArrayList enemies,Point myPoint,Animal my) {
this.enemies = enemies;
this.myPoint = myPoint;
this.my = my;
}
public int Compare(object a,object b) {
if(a==null || b ==null)
return 0;
int ax = ((Point)a).X;
int ay = ((Point)a).Y;
int bx = ((Point)b).X;
int by = ((Point)b).Y;
double besta = -1;
double bestb = -1;
foreach(Point enemy in enemies)
{
double tmpa =((enemy.X-myPoint.X)*ax+(enemy.Y-myPoint.Y)*ay)
/(Math.Sqrt((enemy.X-myPoint.X)*(enemy.X-myPoint.X)+(enemy.Y-myPoint.Y)*(enemy.Y-myPoint.Y))
*Math.Sqrt(ax*ax+ay*ay));
double tmpb =((enemy.X-myPoint.X)*bx+(enemy.Y-myPoint.Y)*by)
/(Math.Sqrt((enemy.X-myPoint.X)*(enemy.X-myPoint.X)+(enemy.Y-myPoint.Y)*(enemy.Y-myPoint.Y))
*Math.Sqrt(bx*bx+by*by));
if(besta < tmpa)
besta = tmpa;
if(bestb < tmpb)
bestb = tmpb;
}
if(my.State.CurrentMoveToAction != null) {
MovementVector mv = my.State.CurrentMoveToAction.MovementVector;
Point D = mv.Destination;
double tmpa =((myPoint.X-D.X)*ax+(myPoint.Y-D.Y)*ay)
/(Math.Sqrt((D.X-myPoint.X)*(D.X-myPoint.X)+(D.Y-myPoint.Y)*(D.Y-myPoint.Y))
*Math.Sqrt(ax*ax+ay*ay));
double tmpb =((myPoint.X-D.X)*bx+(myPoint.Y-D.Y)*by)
/(Math.Sqrt((D.X-myPoint.X)*(D.X-myPoint.X)+(D.Y-myPoint.Y)*(D.Y-myPoint.Y))
*Math.Sqrt(bx*bx+by*by));
if(besta < tmpa)
besta = tmpa;
if(bestb < tmpb)
bestb = tmpb;
}
return (Math.Sign(besta - bestb));
}
private int CellDistance(Point P1 , Point P2)
{
return Math.Max(Math.Abs(P1.X>>3 - P2.X>>3 ),
Math.Abs(P1.Y>>3 - P2.Y>>3 )) - 5;
}
}
/* private class DistComparer2 : IComparer {
ArrayList enemies;
Point myPoint;
public DistComparer2(ArrayList enemies,Point myPoint) {
this.enemies = enemies;
this.myPoint = myPoint;
}
public int Compare(object a,object b) {
if(a==null || b ==null)
return 0;
int da = 0;
int db = 0;
int dax = 0;
int day = 0;
int dbx = 0;
int dby = 0;
int ax = ((Point)a).X<<3;
int ay = ((Point)a).Y<<3;
int bx = ((Point)b).X<<3;
int by = ((Point)b).Y<<3;
foreach(Point enemy in enemies)
{
dax +=enemy.X-(ax+myPoint.X);
day +=enemy.Y-(ay+myPoint.Y);
dbx +=enemy.X-(bx+myPoint.X);
dby +=enemy.Y-(by+myPoint.Y);
}
da=dax*dax+day*day;
db=dbx*dbx+dby*dby;
return((int)(db - da));
}
*/
/* public int Compare(object a,object b) {
if(a==null || b ==null)
return 0;
double da = 0;
double db = 0;
int ax = ((Point)a).X<<3;
int ay = ((Point)a).Y<<3;
int bx = ((Point)b).X<<3;
int by = ((Point)b).Y<<3;
foreach(Point enemy in enemies)
{
int tmp;
tmp =( (enemy.X-(ax+myPoint.X))*(enemy.X-(ax+myPoint.X))
+(enemy.Y-(ay+myPoint.Y))*(enemy.Y-(ay+myPoint.Y)));
if(tmp == 0)
da = int.MaxValue;
else
da +=100000000/tmp;
tmp = ((enemy.X-(bx+myPoint.X))*(enemy.X-(bx+myPoint.X))
+(enemy.Y-(by+myPoint.Y))*(enemy.Y-(by+myPoint.Y))) ;
if(tmp == 0)
db = int.MaxValue;
else
db += 100000000/tmp;
}
return((int)(da - db));
}
*/
private MyCreature my;
private int XSize, YSize;
private int MapPosX, MapPosY;
private int MaxX;
private int MaxY;
private bool[,] blocked ;
private bool[,] creatures ;
public int [,] costs;
private Queue queue ;
Point foundPoint;
Point beginPoint;
ArrayList Direction4;
ArrayList Direction8;
int d,e;
public UtilMap(MyCreature my)
{
this.my=my;
MaxX = my.WorldWidth >> EngineSettings.GridWidthPowerOfTwo;
MaxY = my.WorldHeight>> EngineSettings.GridHeightPowerOfTwo;
XSize = my.Species.EyesightRadius;
YSize = my.Species.EyesightRadius;
Direction4 = new ArrayList(4);
Direction8 = new ArrayList(8);
blocked = new bool[XSize<<1+1,YSize<<1+1];
creatures = new bool[XSize<<1+1,YSize<<1+1];
costs = new int[XSize<<1+1,YSize<<1+1];
queue = new Queue();
/* direction = new Point[2,2,2,4];
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
direction[i,j,k,0]=new Point((i==0?0:1)*(j==0?1:-1),(i==0?1:0)*(k==0?1:-1));
direction[i,j,k,1]=new Point((i==0?1:0)*(j==0?1:-1),(i==0?0:1)*(k==0?1:-1));
direction[i,j,k,2]=new Point((i==0?1:0)*(j==0?-1:1),(i==0?0:1)*(k==0?-1:1));
direction[i,j,k,3]=new Point((i==0?0:1)*(j==0?-1:1),(i==0?1:0)*(k==0?-1:1));
}
*/
for(int x=-1;x<=1;x++)
for(int y=-1;y<=1;y++)
{
if(Math.Abs(x)!=Math.Abs(y))
Direction4.Add(new Point(x,y));
if(x!=0||y!=0)
Direction8.Add(new Point(x,y));
}
}
public void Update()
{
Reset();
foreach(OrganismState creature in my.Plants) {
addBlocker(creature);
}
foreach(OrganismState creature in my.Friends) {
addBlocker(creature);
}
foreach(OrganismState creature in my.kyoi) {
addBlocker(creature);
}
foreach(OrganismState creature in my.esa) {
addBlocker(creature);
}
foreach(OrganismState creature in my.Dead) {
addBlocker(creature);
}
}
public void ResetCost()
{
for(int i=0;i<=XSize<<1;i++)
for(int ii=0;ii<=YSize<<1;ii++)
costs[i,ii] =int.MaxValue;
queue.Clear();
}
private void Reset()
{
d = ((Int32)Math.Round( Math.Cos( (double)my.State.ActualDirection / 180 * Math.PI ) * my.State.Speed ));
e = ((Int32)Math.Round( Math.Sin( (double)my.State.ActualDirection / 180 * Math.PI ) * my.State.Speed ));
MapPosX = my.Position.X >> EngineSettings.GridWidthPowerOfTwo;
MapPosY = my.Position.Y >> EngineSettings.GridHeightPowerOfTwo;
int a = my.State.CellRadius;
int b = MaxX-a;
int c = MaxY-a;
for(int i=0;i<=XSize<<1;i++) {
for(int ii=0;ii<=YSize<<1;ii++)
{
creatures[i,ii] = false;
costs[i,ii] =int.MaxValue;
int x = i+MapPosX-XSize;
int y = ii+MapPosY-YSize;
if(x<=a || x>=b||y<=a || y>=c)
{
blocked[i,ii]= true;
}
else
{
blocked[i,ii]= false;
}
}
}
queue.Clear();
}
private Point GetRealPoint(Point m)
{
Point p = new Point((int)((m.X+MapPosX-XSize)*EngineSettings.GridCellWidth),
(int)((m.Y+MapPosY-YSize)*EngineSettings.GridCellHeight));
return p;
}
public bool findingFood(ArrayList foods)
{
foundPoint = new Point(XSize,YSize);
beginPoint = foundPoint;
foreach(OrganismState food in foods) {
if(my.State.IsAdjacentOrOverlapping(food))
{
return true;
}
addCreature(food);
}
if(creatures[XSize,YSize])
return false;
queue.Enqueue(new Point(XSize,YSize));
costs[XSize,YSize]=0;
while(queue.Count>0&&(foundPoint.X == XSize&&foundPoint.Y == YSize))
calcPath();
if(foundPoint.X!=XSize||foundPoint.Y!=YSize)
{
try{
int speed = 12;
if(my.AS.Count>0)
speed = my.Species.MaximumSpeed;
my.BeginMoving(GetMovementVector2(backTrace2(foundPoint),speed));
return true;
}catch{};
}
return false;
}
public bool chaseenemy(ArrayList foods,int speed)
{
foundPoint = new Point(XSize,YSize);
beginPoint = foundPoint;
costs[beginPoint.X,beginPoint.Y]=0;
if(!my.isBlocked )
{
OrganismState food = (OrganismState) foods[0];
double dist = my.DistanceTo(food);
Point p = food.Position;
if(food.CurrentMoveToAction != null) {
MovementVector mv = food.CurrentMoveToAction.MovementVector;
Point D = mv.Destination;
Vector vector = Vector.Subtract(food.Position,D);
vector = vector.GetUnitVector().Scale(dist * 0.03 * mv.Speed);
p = RangeCheck(Vector.Add(p,vector));
}
/*
if(my.CellDistanceTo(food) < 2){
Point myp = new Point(my.Position.X-d,my.Position.Y-e);
p =RangeCheck(Vector.Add(myp,Vector.Subtract(myp,p).Scale(100)));
speed = my.Species.MaximumSpeed;
}
*/
if(p != Point.Empty)
my.BeginMoving(new MovementVector(p,MinSpeedToReachPointInTick(p,speed)));
/* if(!my.IsMySpecies(food)){
try{
my.BeginAttacking(food as AnimalState);
my.BeginDefending(food as AnimalState);
}
catch{};
}
*/
return true;
}
foreach(OrganismState food in foods) {
addCreature(food);
}
if(creatures[beginPoint.X,beginPoint.Y])
return true;
queue.Enqueue(beginPoint);
Vector v = Vector.Subtract(my.Position,((OrganismState)foods[0]).Position);
Direction4.Sort(new DistComparer(v));
Direction8.Sort(new DistComparer(v));
while(queue.Count>0&&foundPoint == beginPoint)
{
if(my.isBlocked)
{
calcPath();
}
else
{
calcPath2();
}
}
if(foundPoint!=beginPoint)
{
try{
if(my.isBlocked)
my.BeginMoving(GetMovementVector2(backTrace2(foundPoint),speed));
else
my.BeginMoving(GetMovementVector(backTrace(foundPoint),speed));
return true;
}catch{
}
}
return false;
}
private void calcPath()
{
Point p = (Point)(queue.Dequeue());
foreach(Point q in Direction4){
int X = q.X+p.X;
int Y = q.Y+p.Y;
if(X>=0&&Y>=0&&X<=(XSize<<1)&&Y<=(YSize<<1)&&!blocked[X,Y] &&costs[X,Y]>costs[p.X,p.Y]+1)
{
costs[X,Y]=costs[p.X,p.Y]+1;
Point tmp = new Point(X,Y);
if(!queue.Contains(tmp))
queue.Enqueue(tmp);
if(creatures[X,Y] == true)
{
foundPoint= tmp;
return;
}
}
}
}
private void calcPath2()
{
Point p = (Point)(queue.Dequeue());
foreach(Point q in Direction8){
int X = q.X+p.X;
int Y = q.Y+p.Y;
int cost = 0;
if((q.X==-1||q.X==1)&&(q.Y==-1||q.Y==1))
cost = 3;
else
cost = 2;
if(X>=0&&Y>=0&&X<=(XSize<<1)&&Y<=(YSize<<1)&&!blocked[X,Y] &&costs[X,Y]>costs[p.X,p.Y]+cost)
{
costs[X,Y] = costs[p.X,p.Y]+cost;
Point tmp = new Point(X,Y);
if(!queue.Contains(tmp))
queue.Enqueue(tmp);
if(creatures[X,Y] == true)
{
foundPoint= tmp;
return;
}
}
}
}
public void runawayFromEnemy(ArrayList enemies)
{
ArrayList distance=new ArrayList();
foundPoint = new Point(XSize,YSize);
beginPoint = foundPoint;
/* foreach(OrganismState enemy in enemies) {
int xpos = (enemy.Position.X >> EngineSettings.GridWidthPowerOfTwo)-MapPosX+XSize;
int ypos = (enemy.Position.Y >> EngineSettings.GridHeightPowerOfTwo)-MapPosY+YSize;
beginX += xpos;
beginY += ypos;
addCreature(enemy);
}
beginPoint = new Point ((int)(beginX/enemies.Count),(int)(beginY/enemies.Count));
*/
costs[beginPoint.X,beginPoint.Y]=0;
foreach(OrganismState enemy in enemies)
{
distance.Add(enemy.Position);
}
foreach(Point F in my.SeenCarnivores)
distance.Add(F);
Point P = my.Position;
Direction4.Sort(new DistComparer2(distance,P,my));
Direction8.Sort(new DistComparer2(distance,P,my));
if(my.isBlocked)
{
calcPath4(beginPoint.X,beginPoint.Y,Point.Empty);
}
else
{
calcPath5(beginPoint.X,beginPoint.Y,Point.Empty);
}
if(foundPoint!=beginPoint){
AnimalState an;
int speed;
if(enemies.Count>0)
{
an =(AnimalState)enemies[0];
/*
int xpos = (an.Position.X >> EngineSettings.GridWidthPowerOfTwo)-MapPosX;
int ypos = (an.Position.Y >> EngineSettings.GridHeightPowerOfTwo)-MapPosY;
if((foundPoint.X-XSize)*xpos*(foundPoint.Y-YSize)*ypos>0)
a=Math.Abs(an.Position.X-my.Position.X) < Math.Abs(an.Position.Y-my.Position.Y)?0:1;
else
a=(foundPoint.X-XSize)*xpos>0?0:1;
b=an.Position.X<0?0:1;
c=an.Position.Y<0?0:1;
*/
double h = (Vector.Subtract(my.Position,an.Position)).Magnitude;
speed = h>80 ? Math.Min(Math.Max(an.Speed+2 ,3),my.Species.MaximumSpeed) : my.Species.MaximumSpeed;
}
else
speed = 3;
try{
if(my.isBlocked)
my.BeginMoving(GetMovementVector2(backTrace2(foundPoint),speed));
else
my.BeginMoving(GetMovementVector(backTrace(foundPoint),speed));
}catch{
}
}
}
public void randomwalk(Vector v)
{
foundPoint = new Point(XSize,YSize);
beginPoint = foundPoint;
/* foreach(OrganismState enemy in enemies) {
int xpos = (enemy.Position.X >> EngineSettings.GridWidthPowerOfTwo)-MapPosX+XSize;
int ypos = (enemy.Position.Y >> EngineSettings.GridHeightPowerOfTwo)-MapPosY+YSize;
beginX += xpos;
beginY += ypos;
addCreature(enemy);
}
beginPoint = new Point ((int)(beginX/enemies.Count),(int)(beginY/enemies.Count));
*/
costs[beginPoint.X,beginPoint.Y]=0;
if(v != null){
Direction4.Sort(new DistComparer(v));
Direction8.Sort(new DistComparer(v));
}
if(my.isBlocked)
{
calcPath4(beginPoint.X,beginPoint.Y,Point.Empty);
}
else
{
calcPath5(beginPoint.X,beginPoint.Y,Point.Empty);
}
if(foundPoint!=beginPoint){
try{
if(my.isBlocked)
my.BeginMoving(GetMovementVector2(backTrace2(foundPoint),3));
else
my.BeginMoving(GetMovementVector(backTrace(foundPoint),3));
}catch{
}
}
}
private bool calcPath4(int x,int y , Point P)
{
if(x==0||y==0||x==(XSize<<1)||y==(YSize<<1))
{
foundPoint = new Point(x,y);
return true;
}
if(P != Point.Empty ){
if(x+P.X>=0&&y+P.Y>=0&&x+P.X<=(XSize<<1)&&y+P.Y<=(YSize<<1)&&!blocked[x+P.X,y+P.Y] )
{
int cost=costs[x,y]+2;
if(costs[x+P.X,y+P.Y]>cost)
{
costs[x+P.X,y+P.Y]=cost;
if(calcPath4(x+P.X,y+P.Y,P))
return true;
}
}
}
foreach(Point p in Direction4)
if(x+p.X>=0&&y+p.Y>=0&&x+p.X<=(XSize<<1)&&y+p.Y<=(YSize<<1)&&!blocked[x+p.X,y+p.Y] )
{
int cost=costs[x,y]+2;
if(costs[x+p.X,y+p.Y]>cost)
{
costs[x+p.X,y+p.Y]=cost;
if(calcPath4(x+p.X,y+p.Y,p))
return true;
}
}
return false;
}
private bool calcPath5(int x,int y,Point P)
{
if(x==0||y==0||x==(XSize<<1)||y==(YSize<<1))
{
foundPoint = new Point(x,y);
return true;
}
if(P != Point.Empty)
if(x+P.X>=0&&y+P.Y>=0&&x+P.X<=(XSize<<1)&&y+P.Y<=(YSize<<1)&&!blocked[x+P.X,y+P.Y] )
{
int cost;
if((P.X==-1||P.X==1)&&(P.Y==-1||P.Y==1))
cost=costs[x,y]+3;
else
cost=costs[x,y]+2;
if(costs[x+P.X,y+P.Y]>cost)
{
costs[x+P.X,y+P.Y]=cost;
if(calcPath5(x+P.X,y+P.Y,P))
return true;
}
}
foreach(Point p in Direction8)
if(x+p.X>=0&&y+p.Y>=0&&x+p.X<=(XSize<<1)&&y+p.Y<=(YSize<<1)&&!blocked[x+p.X,y+p.Y] )
{
int cost;
if((p.X==-1||p.X==1)&&(p.Y==-1||p.Y==1))
cost=costs[x,y]+3;
else
cost=costs[x,y]+2;
if(costs[x+p.X,y+p.Y]>cost)
{
costs[x+p.X,y+p.Y]=cost;
if(calcPath5(x+p.X,y+p.Y,p))
return true;
}
}
return false;
}
private ArrayList backTrace(Point target)
{
ArrayList ret = new ArrayList();
Point last = target;
int dx = target.X-XSize;
int dy = target.Y-YSize;
ret.Add(target);
while(last!=beginPoint)
{
Point best = last;
foreach(Point p in Direction8)
{
int X=last.X+p.X;
int Y=last.Y+p.Y;
if(X>=0&&X<=XSize<<1&&Y>=0&&Y<=YSize<<1&&costs[X,Y]=0&&X<=XSize<<1&&Y>=0&&Y<=YSize<<1&&costs[X,Y]0)
{
moveTo = (Point) path[1];
moveFrom = (Point) path[0];
}
else
{
return null;;
}
int pos=1;
Point next = (Point)path[0];
Point last;
do
{
last = next;
if(pos0)
{
moveTo = (Point) path[1];
moveFrom = (Point) path[0];
}
else
{
return null;;
}
int pos=1;
Point next = (Point)path[0];
Point last;
do
{
last = next;
if(pos> EngineSettings.GridWidthPowerOfTwo)-MapPosX+XSize;
int ypos = (o.Position.Y >> EngineSettings.GridHeightPowerOfTwo)-MapPosY+YSize;
int size = o.CellRadius+my.State.CellRadius;
for (int i=Math.Max(xpos-size,0); i<=Math.Min(xpos+size,XSize<<1); i++)
for (int ii=Math.Max(ypos-size,0); ii<=Math.Min(ypos+size,YSize<<1); ii++)
{
blocked[i,ii] = true;
}
}
private void addCreature(OrganismState o)
{
int xpos = (o.Position.X >> EngineSettings.GridWidthPowerOfTwo)-MapPosX+XSize;
int ypos = (o.Position.Y >> EngineSettings.GridHeightPowerOfTwo)-MapPosY+YSize;
int size = o.CellRadius+my.State.CellRadius+1;
for (int i=xpos-size; i<=xpos+size; i++)
for (int ii=ypos-size; ii<=ypos+size; ii++)
{
creatures[Math.Max(Math.Min(i,XSize<<1),0),Math.Max(0,Math.Min(ii,YSize<<1))] = true;
}
}
private void addCreature(ArrayList a)
{
foreach(OrganismState o in a)
{
int xpos = (o.Position.X >> EngineSettings.GridWidthPowerOfTwo)-MapPosX+XSize;
int ypos = (o.Position.Y >> EngineSettings.GridHeightPowerOfTwo)-MapPosY+YSize;
int size = o.CellRadius+my.State.CellRadius+1;
for (int i=xpos-size; i<=xpos+size; i++)
for (int ii=ypos-size; ii<=ypos+size; ii++)
{
int x = Math.Max(Math.Min(i,XSize<<1),0);
int y = Math.Max(0,Math.Min(ii,YSize<<1));
bool flag = false;
foreach(OrganismState o2 in a)
{
if(o2 != o && CellDistanceTo( o2 , x + MapPosX - XSize , y + MapPosY - YSize , o.CellRadius)> EngineSettings.GridWidthPowerOfTwo)-MapPosX+XSize;
int ypos = (o.Position.Y >> EngineSettings.GridHeightPowerOfTwo)-MapPosY+YSize;
creatures[Math.Max(Math.Min(xpos,XSize<<1),0),Math.Max(0,Math.Min(ypos,YSize<<1))] = true;
}
protected Point RangeCheck(Point point) {
int x = point.X;
int y = point.Y;
x = (x < 0) ? 0 : (my.WorldWidth <= x) ? my.WorldWidth-1 : x;
y = (y < 0) ? 0 : (my.WorldWidth <= y) ? my.WorldWidth-1 : y;
return new Point(x,y);
}
}
<script language="javascript" src="http://hi.images.csdn.net/js/syntaxhighlighter/scripts/shCore.js"></script><script language="javascript" src="http://hi.images.csdn.net/js/syntaxhighlighter/scripts/shBrushCSharp.js"></script>