Britbot
SmartIsland.cs
Go to the documentation of this file.
00001 #region #Usings
00002 
00003 using System.Collections.Generic;
00004 using Pirates;
00005 
00006 #endregion
00007 
00008 namespace Britbot
00009 {
00013     public class SmartIsland : ITarget
00014     {
00015         #region Fields & Properies
00016 
00020         public readonly int Id;
00021 
00025         public List<KeyValuePair<EnemyGroup,bool>> approachingEnemies;
00026 
00033         public static List<SmartIsland> IslandList { get; private set; }
00034 
00038         public int CaptureTurns
00039         {
00040             get { return Bot.Game.GetIsland(this.Id).CaptureTurns; }
00041         }
00042 
00046         public int Value
00047         {
00048             get { return Bot.Game.GetIsland(this.Id).Value; }
00049         }
00050 
00054         public Location Loc
00055         {
00056             get { return Bot.Game.GetIsland(this.Id).Loc; }
00057         }
00058 
00062         public int TeamCapturing
00063         {
00064             get { return Bot.Game.GetIsland(this.Id).TeamCapturing; }
00065         }
00066 
00070         public int TurnsBeingCaptured
00071         {
00072             get { return Bot.Game.GetIsland(this.Id).TurnsBeingCaptured; }
00073         }
00074 
00078         public int Owner
00079         {
00080             get { return Bot.Game.GetIsland(this.Id).Owner; }
00081         }
00082 
00086         private int _lastAssignmentTurn;
00087 
00088         public int turnsTillColldown;
00089 
00090         public int coolDownCount;
00091         #endregion
00092 
00093         #region Constructors & Initializers
00094 
00098         static SmartIsland()
00099         {
00100             SmartIsland.IslandList = new List<SmartIsland>();
00101             foreach (Island island in Bot.Game.Islands())
00102             {
00103                 SmartIsland.IslandList.Add(new SmartIsland(island.Id));
00104             }
00105         }
00106 
00111         private SmartIsland(int encapsulate)
00112         {
00113             this.Id = encapsulate;
00114             this.approachingEnemies = new List<KeyValuePair<EnemyGroup, bool>>();
00115             //this.SurroundingForces = new Queue<int>()
00116             this.coolDownCount = 0;
00117             this._lastAssignmentTurn = 0;
00118         }
00119 
00120         #endregion
00121 
00122         #region Interface Implementations
00123 
00130         public Score GetScore(Group origin)
00131         {
00132             //constant defining how far to consider enemies capturing the island
00133             int CaptureZone = Bot.Game.GetAttackRadius();
00134 
00135             //check if there are more enemies than we can kill
00136             /*if (this.IsDangerousForGroup(origin) && Magic.UseBasicGlobalizing)
00137             {
00138                 //Bot.Game.Debug("Danger--- Group " + origin.Id + " island: " + this.Id);
00139                 return null;
00140             }*/
00141 
00142             //calculates the minimum distance between a group and said island
00143             int distance = Bot.Game.Distance(this.Loc, origin.FindCenter(true));
00144 
00145             //Amount of turns it takes to capture an island
00146             int captureTime = this.RealTimeTillCapture(Consts.ME);
00147 
00148             //TODO this is disabled in the meanwhile because it caused us to lost
00149             //should be taken into consideration in the score globalizing function
00150             /*if (this.Owner == Consts.ENEMY)
00151                 captureTime *= 2;*/
00152 
00153             //check if the island isn't already ours, if so disqualify it and return null
00154            // if (this.Owner != Consts.ME)
00155                 return new Score(this, TargetType.Island, this.Value, this.NearbyEnemyCount(CaptureZone),
00156                     distance + captureTime, this.TurnsToEnemyCapture(origin), this.islandDensity());
00157             return null;
00158         }
00159 
00164         public Location GetLocation()
00165         {
00166             return Loc;
00167         }
00168 
00175         public Direction GetDirection(Group group)
00176         {
00177             //calculates the direction based on the geographical data from the game
00178             return Navigator.CalculateDirectionToStationeryTarget(group.FindCenter(true), group.Heading, GetLocation());
00179         }
00180 
00181         public TargetType GetTargetType()
00182         {
00183             return TargetType.Island;
00184         }
00185 
00186         public string GetDescription()
00187         {
00188             return "Island, id: " + Id + " location: " + Loc;
00189         }
00190 
00196         public bool Equals(ITarget operandB)
00197         {
00198             SmartIsland b = operandB as SmartIsland;
00199             if (b != null)
00200             {
00201                 return this.Equals(b);
00202             }
00203 
00204             return false;
00205         }
00206 
00211         public void TargetAssignmentEvent()
00212         {
00213             
00214         }
00215 
00219         public void TargetDeAssignmentEvent()
00220         {
00221         }
00222 
00223         #endregion
00224 
00225         public override int GetHashCode()
00226         {
00227             return this.Id;
00228         }
00229 
00230         public static bool IsNearNonOurIsland(Location loc, int Range)
00231         {
00232             foreach (SmartIsland island in SmartIsland.IslandList)
00233             {
00234                 if (island.Owner == Consts.ME)
00235                     continue;
00236 
00237                 if (Bot.Game.Distance(loc, island) < Range)
00238                     return true;
00239             }
00240             return false;
00241         }
00242 
00247         public int NearbyEnemyCount(int dangerRadius = 15)
00248         {
00249             int enemyCount = 0; //amount of enemy pirates in proximity to the Island
00250             /*int closestIslandDistance = 0; //The distance between this Island and the one nearest too it
00251             foreach (SmartIsland eIsland in SmartIsland.IslandList)
00252                 //Calculates the distance between this island and the one nearest
00253             {
00254                 int temp = Bot.Game.Distance(eIsland.Loc, this.Loc);
00255                 if (temp < closestIslandDistance)
00256                 {
00257                     closestIslandDistance = temp;
00258                 }
00259             }*/
00260             foreach (EnemyGroup eGroup in Enemy.Groups)
00261             {
00262                 double distance = eGroup.MinimalSquaredDistanceTo(this.Loc);
00263                 //Checks if the group of islands is near the island and if they are getting closer or farther
00264                 if (distance <= dangerRadius)
00265                 {
00266                     //Calculates the sum of pirates in proximity to the island
00267                     //if distance is 0 then one of the pirates in on the island and we dont need to count it
00268                     if (distance == 0)
00269                         enemyCount = enemyCount + eGroup.EnemyPirates.Count - 1;
00270                     else
00271                         enemyCount = enemyCount + eGroup.EnemyPirates.Count;
00272                 }
00273             }
00274 
00275             return enemyCount;
00276         }
00277 
00282         public int TurnsToEnemyCapture(Group myGroup)
00283         {
00284             int tempDistance;
00285             int minDistance = Bot.Game.GetCols() + Bot.Game.GetRows();
00286 
00287             foreach (EnemyGroup eGroup in Enemy.Groups)
00288             {
00289                 tempDistance = Bot.Game.Distance(this.Loc, eGroup.GetLocation());
00290                 if ((minDistance > tempDistance) && (eGroup.GetMaxFightPower() >= myGroup.FightCount()))
00291                     minDistance = tempDistance;
00292             }
00293 
00294             return minDistance + this.CaptureTurns;
00295         }
00296         //TODO: Calculates the largest distance between islands and the shortest and creates a precentage 
00297         // Another way: Calculate the distance to the nearest next island, the shorter the better
00298         public int islandDensity()
00299         {
00300             int distFromAllIslands=0 ;
00301             foreach (SmartIsland Islands in IslandList)
00302             {
00303                 distFromAllIslands += Bot.Game.Distance(Islands.Loc, this.Loc);                          
00304             }
00305             //Note that a high score in this case is bad and therefor it is multiplied by -1
00306             //When used, the use of a coefficient will most likely be imperative
00307             return distFromAllIslands *-1 ;
00308         }
00309 
00313         public void Update()
00314         {
00315             //---------------#Magic_Numbers--------------------
00316             //constant defining how far to look for enemy ships 
00317             //int DangerZone = 6 * Bot.Game.GetAttackRadius();
00318 
00319             //---------------#Magic_Numbers--------------------
00320             /*const int HowLongToLookBack = 1;
00321             //add new data
00322             this.SurroundingForces.Enqueue(this.NearbyEnemyCount(Magic.DangerZone));
00323 
00324             //trim the end of the queue if needed
00325             if (this.SurroundingForces.Count > HowLongToLookBack)
00326             {
00327                 this.SurroundingForces.Dequeue();
00328             }*/
00329 
00330             //update enemy distances
00331             this.approachingEnemies.Clear();
00332             foreach (EnemyGroup eGroup in Enemy.Groups)
00333             {
00334             //    if(eGroup.MinimalETATo(this.Loc) < Magic.MaxEnemyPredictionDistnace)
00335                     this.approachingEnemies.Add(new KeyValuePair<EnemyGroup, bool>(eGroup, eGroup.IsApproachingIsland(this)));
00336             }
00337             //sort the list by distance
00338             this.approachingEnemies.Sort(
00339                 (e1, e2) => e1.Key.MinimalETATo(this.Loc).CompareTo(e2.Key.MinimalSquaredDistanceTo(this.Loc)));
00340         }
00341 
00347         public double GetMinimumSquareDistanceFromEnemy()
00348         {
00349             //if isn't empty
00350             if (this.approachingEnemies.Count > 0)
00351                 return this.approachingEnemies[0].Key.MinimalSquaredDistanceTo(this.Loc);
00352 
00353             //otherwise return the constant in MAGIC representing the best case scenario
00354             return Magic.MaxCalculableDistance;
00355         }
00356 
00357         public override string ToString()
00358         {
00359             return this.Debug();
00360         }
00361 
00362 
00363         /*public int GetEnemyNum()
00364         {
00365             int max = 0;
00366 
00367             
00368             foreach (int s in this.SurroundingForces)
00369             {
00370                 if (s > max)
00371                     max = s;
00372             }
00373             return max;
00374         }*/
00375 
00376         public static void UpdateAll()
00377         {
00378             foreach (SmartIsland sIsland in SmartIsland.IslandList)
00379             {
00380                 sIsland.Update();
00381             }
00382             SmartIsland.DebugAll();
00383         }
00384 
00385         public string Debug()
00386         {
00387              return "Island " + this.Id + " enemies: " + string.Join(", ", this.approachingEnemies) + this.Loc;
00388         }
00389 
00390         public static void DebugAll()
00391         {
00392             /*Bot.Game.Debug("--------ISLANDS DEBUG----------");
00393             foreach (SmartIsland sIsland in SmartIsland.IslandList)
00394                 sIsland.Debug();*/
00395         }
00396 
00403         public bool IsDangerousForGroup(Group g)
00404         {
00405             //Bot.Game.Debug("IsDangerousForGroup island: " + Id + " group " + g.Id);
00406             //calculate distance in turns till we reach the island
00407             int eta = Bot.Game.Distance(this.Loc, g.FindCenter(true));
00408 
00409             //find the distance of g from the island
00410             int distance = Bot.Game.Distance(this.Loc, g.FindCenter(true));
00411 
00412 
00413             //go over all the enemy groups approaching and their distances
00414             //TODO: maybe consider the actual firepower of the enemy
00415             foreach (KeyValuePair<EnemyGroup,bool> eGroupPair in this.approachingEnemies)
00416             {
00417                 if (!eGroupPair.Value)
00418                     continue;
00419 
00420                 EnemyGroup eGroup = eGroupPair.Key;
00421                 //calculate this enemy groups time of arival
00422                 double EnemyETA = eGroup.MinimalETATo(this.Loc);
00423 
00424                 //read enemy force
00425                 double enemyForce = eGroup.GetMaxFightPower();
00426 
00427                 //We diffarentiate between two cases
00428                 if (EnemyETA < distance) //case 1: Enemy is closer to the island then we are
00429                 {
00430                     //check if we arrive before capture
00431                     if (distance < EnemyETA + this.RealTimeTillCapture(Consts.ENEMY))
00432                     {
00433                         //the enemy who are closer are at disaddvantage since they lose one pirate capturing the island
00434                         if (g.LiveCount() <= enemyForce - 1)
00435                             return true;
00436                     }
00437                 }
00438                 else //case 2: Enemy is farther away to the island then we are
00439                 {
00440                     //if the enemy reaches us before we capture
00441                     if (EnemyETA < this.RealTimeTillCapture(Consts.ME) + distance)
00442                     {
00443                         //for the enemy who are farther, we are at a disaddvantage
00444                         if ((enemyForce != 0) && (g.LiveCount() - 1 < enemyForce))
00445                             return true;
00446 
00447                         //special case: Manuver 
00448                         if ((enemyForce != 0) && (g.LiveCount() - 1 == enemyForce))
00449                         {
00450                             //we would like to run from the island only when they are realy close so we will catch them
00451                             if (eGroup.MinimalSquaredDistanceTo(this.Loc) < Magic.ManeuverDistance)
00452                             {
00453                                 return true;
00454                             }
00455                         }
00456                     }
00457                 }
00458             }
00459 
00460             //if we are here then everything is ok
00461             return false;
00462         }
00463 
00470         public int RealTimeTillCapture(int conqueror)
00471         {
00472             //calculate total number of turns to capture (without partials)
00473             int totalCaptureTime;
00474             //check if conqueror is the owner
00475             if (this.Owner == conqueror)
00476             {
00477                 totalCaptureTime = 0;
00478             } //if the isalnd is nutral
00479             else if (this.Owner == Consts.NO_OWNER)
00480             {
00481                 totalCaptureTime = this.CaptureTurns;
00482             } //if the island is of the other team
00483             else
00484             {
00485                 totalCaptureTime = 2 * this.CaptureTurns;
00486             }
00487 
00488             //check if we already have some capture time
00489             if (this.TeamCapturing == conqueror)
00490             {
00491                 return totalCaptureTime - this.TurnsBeingCaptured;
00492             }
00493             return totalCaptureTime;
00494         }
00495 
00502         public static bool operator ==(SmartIsland a, SmartIsland b)
00503         {
00504             return object.Equals(a, b);
00505         }
00506 
00513         public static bool operator !=(SmartIsland a, SmartIsland b)
00514         {
00515             return !object.Equals(a, b);
00516         }
00517 
00523         protected bool Equals(SmartIsland other)
00524         {
00525             bool eq = this.Id == other.Id;
00526             return eq;
00527         }
00528 
00534         public override bool Equals(object obj)
00535         {
00536             SmartIsland b = obj as SmartIsland;
00537             if (b != null)
00538             {
00539                 return this.Equals(b);
00540             }
00541             return false;
00542         }
00543     }
00544 }