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); } }