/* * * Helper function to compute the not shadowed spaceships after a scan or attack * * returns a dictionary mapping the spaceship to a real ratio (the relative portion of the spaceship that is visible in the scan, shoot * */ public Dictionary <Spaceship, double> SpaceshipsInsideWithShadow(Point a, Point b, Point c) { Spaceship[] sp = ElasticSearchCommands.searchAll().ToArray(); // double represents the shadows Dictionary <Spaceship, double> list = new Dictionary <Spaceship, double>(); var lines = new ArrayList(); lines.Add(new Line(b, c)); var x = this.XCoordinate; var y = this.YCoordinate; var dict = new SortedDictionary <double, Spaceship>(); for (int i = 0; i < sp.Length; i++) { double x_coord = sp[i].XCoordinate; double y_coord = sp[i].YCoordinate; if ((GameMaths.ContainsSpaceship(a, b, c, new Point(x_coord, y_coord), sp[i].Capacity / 100) || GameMaths.IsInside(a, b, c, new Point(x_coord, y_coord))) && this.Name != sp[i].Name) //&& sp[i].Name!="Owen") { double dist = GameMaths.Distance2Points(new Point(x, y), new Point(x_coord, y_coord)); while (dict.ContainsKey(dist)) { dist += 0.2; } dict.Add(dist, sp[i]); } } // find the true non-shadowed spaceships foreach (KeyValuePair <double, Spaceship> kvp in dict) { Spaceship ship = kvp.Value; Point p1, p2; // projections of the tangents to the circle onto BC line Point[] points = GameMaths.PointsOfTangentToCircle(a, new Point(ship.XCoordinate, ship.YCoordinate), ship.Capacity / 100); p1 = points[0]; p2 = points[1]; // get intersection between AP1 and BC (projection of A on BC through a point tangent to the circle/spaceship) points[0] = GameMaths.LineIntersection(a, points[0], b, c); points[1] = GameMaths.LineIntersection(a, points[1], b, c); Array.Sort(points); p1 = points[0]; p2 = points[1]; if (p1 == null || p2 == null) { continue; } int i = 0, j = 0; Boolean found1 = false; Boolean found2 = false; //find where the projections of the points on BC found would sit on the line BC // the points l1,l2 are looking for where p1 sits // the poiints n1, n2 are looking for where p2 sits // modifications in the intervals is necessary // delete all lines between p1 and p2 while (!(found1 && found2)) { // fetch the ith line if (!found1 && i < lines.Count) { Line line = (Line)lines[i]; Point l1 = line.a, l2 = line.b; if (p1.CompareTo(l1) > 0) { if (p1.CompareTo(l2) < 0) { // l1 < p1 < l2 // found the interval where p1 lies, it is not shadowed, so add the spacehsip found1 = true; // check if p1 and p2 are on the same interval if (p2.CompareTo(l1) > 0 && p2.CompareTo(l2) < 0) { list.Add(ship, GameMaths.Distance2Points(p1, p2)); found2 = true; Point aux = ((Line)lines[i]).b; ((Line)lines[i]).b = p1; lines.Insert(i + 1, new Line(p2, aux)); } else { list.Add(ship, GameMaths.Distance2Points(p1, ((Line)lines[i]).b)); ((Line)lines[i]).b = p1; j = i + 1; } } else { // p1 will sit in the next intervals i++; } } else { // p1 lies in an area outside of the lines array, which means it is shadowed // mark l1 as found, but don't add this spaceship to the scanned ones found1 = true; } } if (!found2 && j < lines.Count) { Line line = (Line)lines[j]; Point n1 = line.a, n2 = line.b; if (p2.CompareTo(n1) > 0) { if (p2.CompareTo(n2) < 0) { // n1 < p2 < n2 // found the interval where p2 lies found2 = true; if (list.ContainsKey(ship)) { list[ship] += GameMaths.Distance2Points(((Line)lines[j]).a, p2); } else { list.Add(ship, GameMaths.Distance2Points(((Line)lines[j]).a, p2)); } // restrict the interval for future lookups ((Line)lines[i]).a = p2; } else { // p2 will sit in the next intervals if (found1) { if (list.ContainsKey(ship)) { list[ship] += GameMaths.Distance2Points(((Line)lines[j]).a, ((Line)lines[j]).b); } else { list.Add(ship, GameMaths.Distance2Points(((Line)lines[j]).a, ((Line)lines[j]).b)); } lines.RemoveAt(j); // delete all intervals in between p1 and p2 } else { j++; } } } else { // p2 lies in an area outside of the lines array, which means it is shadowed // mark l1 as found, but don't add this spaceship to the scanned ones found2 = true; } } if (i >= lines.Count) { found1 = true; } if (j >= lines.Count) { found2 = true; } } if (list.ContainsKey(ship)) { list[ship] = list[ship] / GameMaths.Distance2Points(p1, p2); } } return(list); }