Britbot
Navigator.cs
Go to the documentation of this file.
00001 #define MAP_DEBUG
00002 #undef MAP_DEBUG
00003 
00004 #region #Usings
00005 
00006 using System;
00007 using System.Collections.Generic;
00008 using Britbot.PriorityQueue;
00009 using Pirates;
00010 
00011 #endregion
00012 
00013 namespace Britbot
00014 {
00018     internal static partial class Navigator
00019     {
00020         #region Static Fields & Consts
00021 
00022         public static List<long> time = new List<long>();
00023 
00024         #endregion
00025 
00035         public static Direction CalculateDirectionToStationeryTarget(Location myLoc, HeadingVector myHeading,
00036             Location target)
00037         {
00038 /*
00039 
00040             //get the desired direction
00041             HeadingVector desiredVector = HeadingVector.CalcDifference(myLoc, target);
00042 
00043             //variable for the best direction so far
00044             Direction bestDirection = Direction.NOTHING;
00045             double directionFitCoeff = -1;
00046 
00047             //going over all directions
00048             foreach (Direction dir in Bot.Game.GetDirections(myLoc, target))
00049             {
00050                 //calculate new heading vector if we choose this direction
00051                 HeadingVector newHeading = HeadingVector.adjustHeading(myHeading, dir);
00052                 //calculate the dot product with the desired direction and normalize, if it is close to 1 it 
00053                 //means that we are almost in the right direction
00054                 double newFitCoef = newHeading.Normalize() * desiredVector.Normalize();
00055                 
00056                 //check if this direction is better (coefficient is larger) then the others
00057                 if (newFitCoef > directionFitCoeff)
00058                 {
00059                     //replace best
00060                     bestDirection = dir;
00061                     directionFitCoeff = newFitCoef;
00062                 }
00063             }
00064 
00065             //return best direction found
00066             return bestDirection;*/
00067             Logger.BeginTime("CalculateDirectionToStationeryTarget");
00068             Direction d;
00069             //first check if we are already at the target
00070             if (myLoc.Equals(target))
00071                 d = Direction.NOTHING;
00072             else
00073             //otherwise use the A* thing
00074 
00075                 d = Navigator.CalculatePath(myLoc, target);
00076             Logger.StopTime("CalculateDirectionToStationeryTarget");
00077             return d;
00078         }
00079 
00091         public static Direction CalculateDirectionToMovingTarget(Location myLoc, HeadingVector myHeading,
00092             Location target, HeadingVector targetHeading)
00093         {
00094             //defining parameters for calculation (see image 1 under calculations)
00095             double a = targetHeading.Norm1();
00096             double b = target.Col - myLoc.Col;
00097             double c = targetHeading.X;
00098             double d = target.Row - myLoc.Row;
00099             double e = targetHeading.Y;
00100 
00101             //calculating r, hopefully
00102             double r = Navigator.SolveStupidEquation(a, b, c, d, e);
00103 
00104             //finally, calculating the intersection point
00105             Location intersection = HeadingVector.AddvanceByVector(target, r * targetHeading);
00106 
00107             //returning path to intersection
00108             return Navigator.CalculateDirectionToStationeryTarget(myLoc, myHeading, intersection);
00109         }
00110 
00122         public static double SolveStupidEquation(double a, double b, double c, double d, double e)
00123         {
00124             //TODO fix this
00125             int[] signs = {-1, 1};
00126             //there are 4 options, going over them 2 by 2
00127             for (int i = 0; i <= 1; i++) //i is the sign of c in r
00128             {
00129                 int cSign = signs[i];
00130                 for (int j = 0; j <= 1; j++) //j is the sign of e in r
00131                 {
00132                     int eSign = signs[j];
00133                     double r = -(cSign * b + eSign * d) / (a + cSign * c + eSign * e);
00134 
00135                     //check if r isn't positive, if so we can skip it
00136                     if (r <= 0)
00137                         continue;
00138 
00139                     //else check the critirions
00140                     if ((cSign * c * r <= -cSign * b) && (eSign * e * r <= -eSign * d))
00141                     {
00142                         //it is (probably?) the correct r
00143                         return r;
00144                     }
00145                 }
00146             }
00147 
00148             //if we are here then i am wrong :)
00149             Logger.Write("MATAN K IS AN IDIOT");
00150             return 1;
00151         }
00152 
00161         public static double CalcDistFromLine(Location point, Location linePoint, HeadingVector dir)
00162         {
00163             //first check if no direction
00164             if (dir.NormSquared() == 0)
00165                 return Bot.Game.Distance(point, linePoint);
00166 
00167             //TODO fix this - Matan Kom
00168             //Find the difference vector between the point and the line point
00169             HeadingVector dif = HeadingVector.CalcDifference(point, linePoint);
00170             //find the minimum t parameter
00171             double tMin = (-1 / dir.NormSquared()) * dir * dif;
00172 
00173             //calculating actual distance (see calculation)
00174             return (dif + tMin * dir).Norm();
00175             ;
00176         }
00177 
00185         public static int ComparePirateByDirection(int p1, int p2, HeadingVector hv)
00186         {
00187             HeadingVector originDif = new HeadingVector(Bot.Game.GetMyPirate(p1).Loc.Col,
00188                 Bot.Game.GetMyPirate(p1).Loc.Row);
00189             int coef;
00190 
00191             if (originDif * hv > 0)
00192                 coef = 1;
00193             else
00194                 coef = -1;
00195             //calculate both pirates position on the line created by hv
00196             double p1Dist = Navigator.CalcDistFromLine(new Location(0, 0), (Bot.Game.GetMyPirate(p1)).Loc,
00197                 hv.Orthogonal());
00198             double p2Dist = Navigator.CalcDistFromLine(new Location(0, 0), (Bot.Game.GetMyPirate(p2)).Loc,
00199                 hv.Orthogonal());
00200 
00201             return coef * p1Dist.CompareTo(p2Dist);
00202         }
00203 
00211         public static bool IsReachable(Location group, Location target, HeadingVector targetHeading)
00212         {
00213             //if the target is stationary then return true
00214             if (targetHeading.Norm() == 0)
00215                 return true;
00216             //first check if it is running away (its direction is about the same as the difference between you
00217             if (HeadingVector.CalcDifference(group, target) * targetHeading > 0)
00218                 return false;
00219 
00220 
00221             //----------------------calculation of naive maximum intersection----------------------
00222             HeadingVector diffVector = HeadingVector.CalcDifference(target, group);
00223 
00224             double cosAlpha = diffVector.Normalize() * targetHeading.Normalize();
00225             double sacleCoeff = diffVector.Norm() * cosAlpha;
00226 
00227             Location maxIntersection = HeadingVector.AddvanceByVector(target, sacleCoeff * targetHeading.Normalize());
00228             //----------------------------------------------------------------------------------------
00229 
00230             //to account for numeric mistakes we take antitolerance coefficient
00231             const int antiToleranceCoeff = 2;
00232 
00233             //compare distances
00234             //check who is closer
00235             if (Bot.Game.Distance(group, maxIntersection) <
00236                 Bot.Game.Distance(target, maxIntersection) - antiToleranceCoeff)
00237                 return true;
00238 
00239             return false;
00240         }
00241 
00250         public static Direction CalculatePath(Location start, Location target)
00251         {
00252             Logger.BeginTime("CalculatePath");
00253             //first set up the for a new target calculation
00254             Node.SetUpCalculation(target);
00255             //Priority queue of the currently checked nodes. Thank You BlueRaja
00256             HeapPriorityQueue<Node> openset = new HeapPriorityQueue<Node>(Bot.Game.GetCols() * Bot.Game.GetRows());
00257 
00258             //set the beginning
00259             Node beginning = Node.GetLocationNodeFromMap(start);
00260             openset.Enqueue(beginning, beginning.F());
00261 
00262             //begin the iteration
00263             while (openset.Count > 0)
00264             {
00265                 //get the current Node from the top of the openset priority queue
00266                 Node currentNode = openset.Dequeue();
00267 
00268                 //check if it is out target, if so we are done
00269                 if (currentNode.Loc.Equals(target))
00270                     break;
00271 
00272                 //set current node status
00273                 currentNode.IsEvaluated = true;
00274 
00275                 //going over the Neighbors of the current cell
00276                 foreach (Node neighbor in currentNode.GetNeighbors())
00277                 {
00278                     //if we already calculated this neighbor, skip to the next
00279                     if (neighbor.IsEvaluated)
00280                         continue;
00281 
00282                     //calculate the new G score from this rout
00283                     double tentativeG = currentNode.G + neighbor.Weight;
00284                     // double tentativeG = currentNode.G + 1;
00285 
00286                     //if the neighbor isn't in the open set
00287                     //or we just found a better score for him (tentativeG < G)
00288                     //or if G value is default -1
00289                     //then add him to openset
00290                     if ((!openset.Contains(neighbor)) || (neighbor.G == -1) || (tentativeG < neighbor.G))
00291                     {
00292                         //update G score
00293                         neighbor.G = tentativeG;
00294 
00296                         if (!openset.Contains(neighbor))
00297                         {
00298                             openset.Enqueue(neighbor, neighbor.F());
00299                         }
00300                         else //update
00301                         {
00302                             openset.UpdatePriority(neighbor, neighbor.F());
00303                         }
00304                     }
00305                 }
00306                 //update current node
00307                 currentNode.IsEvaluated = true;
00308             }
00309             Logger.StopTime("CalculatePath");
00310 
00311 #if MAP_DEBUG
00312             Node.DebugPasses();
00313 #endif
00314             //now we have made the necessary calculations, just get the desired direction
00315             return Navigator.FindBestDirectionOutOfMap(beginning);
00316         }
00317 
00324         private static Direction FindBestDirectionOutOfMap(Node beginning)
00325         {
00326             Node bestNextNode = null;
00327 
00328             //go over the neighbors of the begining
00329             foreach (Node neighbor in beginning.GetNeighbors())
00330             {
00331                 //if bestNode is null update and skip to next iteration
00332                 if (bestNextNode == null)
00333                 {
00334                     bestNextNode = neighbor;
00335                     continue;
00336                 }
00337                 //if this neighbors score is better then update
00338                 if (neighbor.F() < bestNextNode.F())
00339                 {
00340                     bestNextNode = neighbor;
00341                 }
00342             }
00343             //check if best node is null, if so then i am an idiot and YOU NEED TO INFORM ME OF THAT IMMIDIATELY
00344             if (bestNextNode == null)
00345             {
00346                 Logger.Write("--------------------------------------------------------------------------");
00347                 Logger.Write("--------------------------------------------------------------------------");
00348                 Logger.Write("--------------------------------------------------------------------------");
00349                 Logger.Write("            Matan K is stupid as shit, please go and tell him that");
00350                 Logger.Write("--------------------------------------------------------------------------");
00351                 Logger.Write("--------------------------------------------------------------------------");
00352                 Logger.Write("--------------------------------------------------------------------------");
00353                 return Direction.NOTHING;
00354                 //throw new Exception("Matan K is stupid as shit, please go and tell him that");
00355             }
00356             return Bot.Game.GetDirections(beginning.Loc, bestNextNode.Loc)[0];
00357         }
00358 
00364         public static void UpdateMap(Group group)
00365         {
00366             Node.UpdateMap(group);
00367         }
00368     }
00369 }