Exemple #1
0
        public void Maths_LineIntersection_CorrectPoint()
        {
            Point A = new Point(0, 5);
            Point B = new Point(10, 5);
            Point C = new Point(5, 0);
            Point D = new Point(5, 10);

            Point intersectionPoint = GameMaths.LineIntersection(A, B, C, D);

            Assert.AreEqual(intersectionPoint.x, 5);
            Assert.AreEqual(intersectionPoint.y, 5);
        }
        public String Shoot(double polarAngle, double scanAngle, int energy, String attackCode)
        {
            string bigoutput = "";

            if (this.Energy < energy)
            {
                Console.WriteLine("You do not have enough energy to shoot");
                return(null);
            }
            this.Energy -= energy;
            // cordinates of the spaceship
            // cordinates of the spaceship
            double x = this.XCoordinate;
            double y = this.YCoordinate;

            int r = this.Capacity / 100;

            ArrayList list = new ArrayList();

            int dist = (int)Math.Round(energy / Math.Abs(Math.Sin((Math.PI - scanAngle) / 2 * Math.PI / 180.0)), 0);

            double xA = Math.Round(x + r * Math.Cos(polarAngle * Math.PI / 180.0), 2);
            double yA = Math.Round(y + r * Math.Sin(polarAngle * Math.PI / 180.0), 2);
            // B and C are points of the scan extremes

            double xB = Math.Round(xA + dist * Math.Cos((polarAngle - scanAngle * 0.5) * Math.PI / 180.0), 2);
            double yB = Math.Round(yA + dist * Math.Sin((polarAngle - scanAngle * 0.5) * Math.PI / 180.0), 2);


            double xC = Math.Round(xA + dist * Math.Cos((polarAngle + scanAngle * 0.5) * Math.PI / 180.0), 2);
            double yC = Math.Round(yA + dist * Math.Sin((polarAngle + scanAngle * 0.5) * Math.PI / 180.0), 2);

            Point a, b, c;

            a = new Point(xA, yA);
            b = new Point(xB, yB);
            c = new Point(xC, yC);

            // get a list of the planets and spacehsips
            // check if they are inside the triangle ABC
            // or if the sides of the triangle cu the spaceships (as a circle)

            var dict = this.SpaceshipsInsideWithShadow(a, b, c);


            foreach (KeyValuePair <Spaceship, double> kvp in dict)
            {
                Console.WriteLine("You attacked " + ((Spaceship)(kvp.Key)).Name + " with ratio " + kvp.Value);
            }

            foreach (KeyValuePair <Spaceship, double> kvp in dict)
            {
                Console.WriteLine("You attacked " + ((Spaceship)(kvp.Key)).Name + " with ratio " + kvp.Value);
                Spaceship ship = kvp.Key;
                list.Add(ship);

                double x_coord      = ship.XCoordinate;
                double y_coord      = ship.YCoordinate;
                int    other_radius = ship.Capacity / 100;

                double ratio;   // ratio of the energy with which we are attacking

                // if the spaceship is inside the shoot array'

                if (GameMaths.IsInside(a, b, c, new Point(x_coord, y_coord)))
                {
                    // B'C' is parallel to BC, we need the the slope and the other spaceship coordinates to find the equation and distance of B'C'

                    double slope = (yB - yC) / (xB - xC);

                    // find an equation of the type y = slope * x + b_
                    // aim: find out another point on B'C'

                    double b_          = y_coord - slope * x_coord;
                    double x_new_point = 1; // random, doesn't matter
                    double y_new_point = slope * x_new_point + b_;

                    Point b_prime = GameMaths.LineIntersection(a, b, new Point(x_coord, y_coord), new Point(x_new_point, y_new_point));
                    Point c_prime = GameMaths.LineIntersection(a, c, new Point(x_coord, y_coord), new Point(x_new_point, y_new_point));

                    double dist_b_c_prime = GameMaths.Distance2Points(b_prime, c_prime);

                    // multiple cases depending on where the spaceship lies on the line

                    if (GameMaths.DistanceToLine(GameMaths.LineEquation(a, b), x_coord, y_coord) < other_radius)  // other spaceship is closer to AB, and extends outside
                    {
                        double distance_to_ab = GameMaths.DistanceToLine(GameMaths.LineEquation(a, b), x_coord, y_coord);


                        double dist_to_add;
                        double b_o_dist = distance_to_ab * Math.Sin(((Math.PI - scanAngle) / 2) * Math.PI / 180.0);

                        if (dist_b_c_prime - b_o_dist >= other_radius)
                        {
                            dist_to_add = other_radius;
                        }
                        else
                        {
                            dist_to_add = dist_b_c_prime - b_o_dist;
                        }


                        ratio = (dist_to_add + b_o_dist) / dist_b_c_prime;
                    }

                    else if (GameMaths.DistanceToLine(GameMaths.LineEquation(a, c), x_coord, y_coord) < other_radius)
                    {
                        double distance_to_ac = GameMaths.DistanceToLine(GameMaths.LineEquation(a, c), x_coord, y_coord);


                        double dist_to_add;
                        double c_o_dist = distance_to_ac * Math.Sin(((Math.PI - scanAngle) / 2) * Math.PI / 180.0);

                        if (dist_b_c_prime - c_o_dist >= other_radius)
                        {
                            dist_to_add = other_radius;
                        }
                        else
                        {
                            dist_to_add = dist_b_c_prime - c_o_dist;
                        }


                        ratio = (dist_to_add + c_o_dist) / dist_b_c_prime;
                    }

                    else
                    {
                        // spaceship is on the line equally distributed
                        if (2 * other_radius < dist_b_c_prime)
                        {
                            ratio = (2 * other_radius) / dist_b_c_prime;
                        }
                        else
                        {
                            ratio = 1;
                        }
                    }

                    ratio     += dict[ship];
                    ratio     /= 2;
                    ratio     *= (StringDistance.Compute(ship.Code, attackCode) / 16.0 + 1) / 2.0;
                    bigoutput += this.Attack(ship, (int)(Math.Round((energy * ratio), 0)));
                }


                // if the other spacehsip center is outside of the shoot triangle

                else if (GameMaths.ContainsSpaceship(a, b, c, new Point(x_coord, y_coord), other_radius))
                //   && this.UserId != ship.UserId)
                {
                    // B'C' is parallel to BC, we need the the slope and the other spaceship coordinates to find the equation and distance of B'C'

                    double slope = (yB - yC) / (xB - xC);

                    // find an equation of the type y = slope * x + b
                    // aim: find out another point on B'C'

                    double b_          = y_coord - slope * x_coord;
                    double x_new_point = 1; // random, doesn't matter
                    double y_new_point = slope * x_new_point + b_;

                    Point b_prime = GameMaths.LineIntersection(a, b, new Point(x_coord, y_coord), new Point(x_new_point, y_new_point));
                    Point c_prime = GameMaths.LineIntersection(a, c, new Point(x_coord, y_coord), new Point(x_new_point, y_new_point));

                    double dist_b_c_prime = GameMaths.Distance2Points(b_prime, c_prime);

                    ratio = (other_radius - GameMaths.SmallestDistance(a, b, c, new Point(x_coord, y_coord), other_radius)) / dist_b_c_prime;


                    ratio     += dict[ship];
                    ratio     /= 2;
                    ratio     *= (StringDistance.Compute(ship.Code, attackCode) / 16.0 + 1) / 2.0;
                    bigoutput += this.Attack(ship, (int)(Math.Round((energy * ratio), 0)));
                }
            }

            return(bigoutput);
        }
        /*
         *
         *  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);
        }