|
Britbot
|
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 }
1.7.6.1