Britbot
Node.cs
Go to the documentation of this file.
00001 #region #Usings
00002 
00003 using System;
00004 using System.Collections.Generic;
00005 using Britbot.PriorityQueue;
00006 using Pirates;
00007 
00008 #endregion
00009 
00010 namespace Britbot
00011 {
00015     internal static partial class Navigator
00016     {
00017         #region Fields & Properies
00018 
00022         internal class Node : PriorityQueueNode
00023         {
00024             #region Static Fields & Consts
00025 
00030             public const double Infinity = 100;
00031 
00036             public static Node[,] Map = new Node[Bot.Game.GetRows(), Bot.Game.GetCols()];
00037 
00038             #endregion
00039 
00040             #region Fields & Properies
00041 
00046             public double G;
00047 
00051             public double H;
00052 
00056             public bool IsEvaluated;
00057 
00061             public Location Loc;
00062 
00066             public double Weight;
00067 
00068             #endregion
00069 
00070             #region Constructors & Initializers
00071 
00075             static Node()
00076             {
00077                 for (int y = 0; y < Node.Map.GetLength(0); y++)
00078                 {
00079                     for (int x = 0; x < Node.Map.GetLength(1); x++)
00080                     {
00081                         Node.Map[y, x] = new Node();
00082 
00083                         //set locations
00084                         Node.Map[y, x].Loc = new Location(y, x);
00085                     }
00086                 }
00087             }
00088 
00089             #endregion
00090 
00097             public static void UpdateMap(Group group)
00098             {
00099                 //reading board size
00100                 int cols = Bot.Game.GetCols();
00101                 int rows = Bot.Game.GetRows();
00102 
00103                 //get the radius of the group
00104 
00105                 //go over the entire map, set locations and their wight
00106                 for (int x = 0; x < cols; x++)
00107                 {
00108                     for (int y = 0; y < rows; y++)
00109                     {
00110                         //check if this is passable
00111                         //if (!Bot.Game.IsPassableEnough(Node.Map[y, x].Loc, groupRadius))
00112                         if (!Bot.Game.IsPassableEnough(Node.Map[y, x].Loc, group))
00113                         {
00114                             //set the weight of the node to "infinity"
00115                             Node.Map[y, x].Weight = Node.Infinity;
00116 
00117                             //if so then we are finished here, move to next Node
00118                             continue;
00119                         }
00120 
00121                         // Node.Map[y, x].Weight = Node.CalcEnemyFactor(Node.Map[y, x].Loc, groupStrength);
00122                         Node.Map[y, x].Weight = 1;
00123                         //now set the wight based on enemyGroups
00124                         //double enemyFactor = Node.CalcEnemyFactor(Node.Map[y, x].Loc, groupStrength);
00125                     }
00126                 }
00127                 //update enemy threat
00128 
00129                 Node.CalculateEnemyWeight(group.FightCount());
00130 
00131                 //TODO: update also friendly location
00132             }
00133 
00139             public static void CalculateEnemyWeight(int strength)
00140             {
00141                 Logger.BeginTime("CalculateEnemyWeight");
00142                 //---------------#Magic_Numbers--------------------
00143                 //Important constants of the functions
00144                 //the radious under wich to define locations in danget of enemy groups
00145                 //the higher it is, the performence are worse
00146                 //int DangerRadious = 9 * Bot.Game.GetAttackRadius();
00147 
00148                 //going over enemy fleets and giving their location negative scores
00149                 foreach (EnemyGroup eGroup in Enemy.Groups)
00150                 {
00151                     if (eGroup.GetMaxFightPower() >= strength)
00152                     {
00153                         foreach (int p in eGroup.EnemyPirates)
00154                             Node.BlockLocation(Bot.Game.GetEnemyPirate(p).Loc, Magic.DangerZone, eGroup.GetHeading());
00155                     }
00156                 }
00157                 Logger.StopTime("CalculateEnemyWeight");
00158             }
00159 
00166             private static void BlockLocation(Location loc, double radSquared, HeadingVector heading)
00167             {
00168                 //---------------#Magic_Numbers--------------------
00169                 //important constants:
00170                 //this determines how much we consider the heading of the danger, meaning how elipsy the 
00171                 //danger zone will be
00172                 const double headingFactor = 0.25;
00173 
00174                 //reading some important parameters
00175                 int rad = (int) Math.Sqrt(radSquared);
00176                 int maxX = Bot.Game.GetCols() - 1;
00177                 int maxY = Bot.Game.GetRows() - 1;
00178 
00179                 //going over a square centered at loc
00180                 for (int x = Math.Max(loc.Col - rad, 0); x <= Math.Min(loc.Col + rad, maxX); x++)
00181                 {
00182                     for (int y = Math.Max(loc.Row - rad, 0); y <= Math.Min(loc.Row + rad, maxY); y++)
00183                     {
00184                         //the current location
00185                         Location currLoc = new Location(y, x);
00186 
00187                         //blocking stuff according to their radious and direction
00188                         HeadingVector diffVector = HeadingVector.CalcDifference(loc, currLoc);
00189 
00190                         //calculate the distance considering the heading of the danger
00191                         //if the current location is straight in the direction of the danger we add by proportion to headingFactor
00192                         //if it is in the opposite direction we subtract according to headingFactor
00193                         double distandeSquare = Bot.Game.EuclidianDistanceSquared(new Location(y, x), loc) +
00194                                                 headingFactor * heading.Normalize() * diffVector;
00195                         if (distandeSquare <= radSquared)
00196                             Node.Map[y, x].Weight += Node.Infinity * (radSquared - distandeSquare) / radSquared;
00197                     }
00198                 }
00199             }
00200 
00207             public static void SetUpCalculation(Location target)
00208             {
00209                 Logger.BeginTime("SetUpCalculation");
00210                 //going over all the cells in the Map updating their heuristic value to be 
00211                 //distance from target
00212                 for (int y = 0; y < Bot.Game.GetRows(); y++)
00213                 {
00214                     for (int x = 0; x < Bot.Game.GetCols(); x++)
00215                     {
00216                         Node.Map[y, x].H = Node.HuristicFunction(Node.Map[y, x].Loc, target);
00217 
00218                         //set the calculated G parameter to -1
00219                         Node.Map[y, x].G = -1;
00220 
00221                         Node.Map[y, x].IsEvaluated = false;
00222                     }
00223                 }
00224                 Logger.StopTime("SetUpCalculation");
00225             }
00226 
00234             public static double HuristicFunction(Location loc1, Location loc2)
00235             {
00236                 //if we chose euclidian huristic
00237                 if (Magic.EuclidianHuristic)
00238                     return Bot.Game.EuclidianDistanceSquared(loc1, loc2);
00239                 // Manhatten huristic
00240                 return Bot.Game.Distance(loc1, loc2);
00241             }
00242 
00248             public static Node GetLocationNodeFromMap(Location loc)
00249             {
00250                 return Node.Map[loc.Row, loc.Col];
00251             }
00252 
00257             public double F()
00258             {
00259                 return (this.H + this.G);
00260             }
00261 
00266             public bool IsPassable()
00267             {
00268                 return this.Weight < Node.Infinity;
00269             }
00270 
00271             public static void DebugPasses()
00272             {
00273                 string line = "";
00274                 for (int i = 0; i < Node.Map.GetLength(0); i++)
00275                 {
00276                     for (int j = 0; j < Node.Map.GetLength(1); j++)
00277                     {
00278                         if (Node.Map[i, j].G == -1 && Node.Map[i, j].Weight < 3)
00279                             line += "*";
00280                         else if (Node.Map[i, j].H == 0)
00281                             line += "O";
00282                         else if (Node.Map[i, j].Weight >= 3)
00283                             line += "X";
00284                         else
00285                             line += "-";
00286                     }
00287                     Logger.Write(line);
00288                     line = "";
00289                 }
00290             }
00291 
00297             public List<Node> GetNeighbors()
00298             {
00299                 //allocating a new list
00300                 List<Node> neighbors = new List<Node>();
00301 
00302                 //array to help iterating over the four neighbors
00303                 int[] coeff = {-1, 1};
00304 
00305                 //read X and Y from this.loc
00306                 int X = this.Loc.Col;
00307                 int Y = this.Loc.Row;
00308 
00309 
00310                 //going over neighbors
00311                 for (int delata = 0; delata < 2; delata++)
00312                 {
00313                     //get the iterated neighbor coordinates
00314                     int neighborX = X + coeff[delata];
00315                     int neighborY = Y;
00316 
00317                     //check if out of bounderie, if so, continue to next iteration
00318                     if ((neighborX < 0) || (neighborX >= Bot.Game.GetCols()) ||
00319                         (neighborY < 0) || (neighborY >= Bot.Game.GetRows()))
00320                         continue;
00321 
00322                     //check if impassable, if so, continue to next iteration
00323                     /*if (!Node.Map[neighborY, neighborX].IsPassable())
00324                         continue;*/
00325 
00326                     //if we are here it means that the neighbor is ok, so add him to the list
00327                     neighbors.Add(Node.Map[neighborY, neighborX]);
00328                 }
00329                 for (int delata = 0; delata < 2; delata++)
00330                 {
00331                     //get the iterated neighbor coordinates
00332                     int neighborX = X;
00333                     int neighborY = Y + coeff[delata];
00334 
00335                     //check if out of bounderie, if so, continue to next iteration
00336                     if ((neighborX < 0) || (neighborX >= Bot.Game.GetCols()) ||
00337                         (neighborY < 0) || (neighborY >= Bot.Game.GetRows()))
00338                         continue;
00339 
00340                     //check if impassable, if so, continue to next iteration
00341                     /* if (!Node.Map[neighborY, neighborX].IsPassable())
00342                         continue;*/
00343 
00344                     //if we are here it means that the neighbor is ok, so add him to the list
00345                     neighbors.Add(Node.Map[neighborY, neighborX]);
00346                 }
00347                 return neighbors;
00348             }
00349         }
00350 
00351         #endregion
00352     }
00353 }