示例#1
0
        private void Fire(Tank self, World world, Move move)
        {
            double angleToTank = double.MaxValue;
            Tank selectedTank = null;

            foreach (Tank tank in world.Tanks)
            {
                if (tank.IsTeammate) continue;
                if (tank.CrewHealth < 1 || tank.HullDurability < 1) continue;

                double angle = self.GetTurretAngleTo(tank);

                if (Math.Abs(angle) < Math.Abs(angleToTank))
                {
                    angleToTank = angle;
                    selectedTank = tank;
                }
            }

            if (selectedTank == null) return;

            Ray ray = new Ray(self.Id, self.X, self.Y, self.Angle + self.TurretRelativeAngle);
            Location expectedLocation = selectedTank.GetExpectedPositionForFire<Location>(self, world);

            double expectedAngle = self.GetTurretAngleTo(expectedLocation.X, expectedLocation.Y);
            double distance = self.GetDistanceTo(selectedTank);

            // if we can shoot enemy
            if (ray.IsCollide(selectedTank) && !selectedTank.IsCovered(ray, world))
            {
                if (distance < self.Width)
                {
                    move.FireType = FireType.PremiumPreferred;
                }
                else if (distance < 3.0d * self.Width && Math.Abs(expectedAngle) < 2.0d * Const.MIN_ANGLE)
                {
                    move.FireType = FireType.PremiumPreferred;
                }
                else if (Math.Abs(expectedAngle) < Const.MIN_ANGLE)
                {
                    move.FireType = FireType.Regular;
                }
            }
            if (expectedAngle > 0)
            {
                move.TurretTurn = self.TurretTurnSpeed;
            }
            else
            {
                move.TurretTurn = -self.TurretTurnSpeed;
            }
        }
示例#2
0
        private double TurretCoeff(Tank self, Unit goal)
        {
            double minDist = 10000;
            for (int i = 0; i < world.Tanks.Length; i++)
                if (!world.Tanks[i].IsTeammate && IsAlive(world.Tanks[i]))
                    if (minDist > self.GetDistanceTo(world.Tanks[i]))
                        minDist = self.GetDistanceTo(world.Tanks[i]);

            if (minDist > self.Width * 6)
            {
                double angle = Math.Abs(NormAngle(goal.Angle - NormAngle(self.GetTurretAngleTo(goal) + self.Angle + self.TurretRelativeAngle)));
                if (angle > Angle[90])
                    angle = Angle[180] - angle;
                return 1 / angle;
            }

            if (world.Tick > 30)
                return 1 / self.GetDistanceTo(goal);

            return 1 / Math.Abs(self.GetTurretAngleTo(goal));
        }
示例#3
0
        public void Move(Tank self, World world, Move move)
        {
            if (start == -1)
            {
                start = self.TeammateIndex == 0 ? 10 : 20;
                int cnt = 0;
                foreach (Tank t in world.Tanks)
                    if (t.IsTeammate)
                        cnt++;
                gameType = cnt - 1;
            }

            // определяю центральный прямоугольник
            x1 = world.Width * 0.25;
            x2 = world.Width - x1;
            y1 = world.Height * 0.25;
            y2 = world.Height - y1;
            rectX = new double[] { x1, x2, x2, x1 };
            rectY = new double[] { y1, y1, y2, y2 };
            this.world = world;
            this.move = move;

            int bonusId = SelectBonus(self);

            int selectedTank = world.Tanks.Length;

            if (bonusId != world.Bonuses.Length)
            {
                Go(self, world.Bonuses[bonusId].X, world.Bonuses[bonusId].Y);
            }
            else
            {
                double[] bestPos = FindBestPosition(self);
                Go(self, bestPos[0], bestPos[1]);
            }

            // теперь находим максимально удобную цель для стрельбы
            selectedTank = world.Tanks.Length;
            double maxK = 0;
            bool goalFinded = false;
            for (int i = 0; i < world.Tanks.Length; i++)
            {
                if (!world.Tanks[i].IsTeammate && IsAlive(world.Tanks[i]) && !Intersected(self, world.Tanks[i]))
                {
                    double k = TurretCoeff(self, world.Tanks[i]);
                    if (k > maxK)
                    {
                        maxK = k;
                        selectedTank = i;
                        goalFinded = true;
                    }
                }
            }

            if (!goalFinded)
            {
                // если не нашли цель для стрельбы - ищем не обращая внимания на препятствия
                for (int i = 0; i < world.Tanks.Length; i++)
                {
                    if (!world.Tanks[i].IsTeammate && IsAlive(world.Tanks[i]))
                    {
                        double k = TurretCoeff(self, world.Tanks[i]);
                        if (k > maxK)
                        {
                            maxK = k;
                            selectedTank = i;
                        }
                    }
                }
            }
            if (selectedTank == world.Tanks.Length)
                return;

            bool gogogo = false;
            if (world.Tick > 200)
            {
                // Проверяю что в меня могут попасть
                int check = CheckToBeWounded(self, 2);
                if (check != 0)
                {
                    int c0 = CheckToBeWounded(self, 0);
                    // Стоять на месте
                    if (c0 == 0)
                    {
                        SetMove(0, 0);
                        gogogo = true;
                    }
                    else
                    {
                        double speed = GetSpeed(self);
                        int c1 = CheckToBeWounded(self, 1);
                        // Вперёд
                        double AngleBetweenSelfAndSpeed = self.Angle - Math.Atan2(self.SpeedY, self.SpeedX); // угол между скоростью и мной
                        AngleBetweenSelfAndSpeed = NormAngle(AngleBetweenSelfAndSpeed);
                        if (AngleBetweenSelfAndSpeed < 0)
                            AngleBetweenSelfAndSpeed = -AngleBetweenSelfAndSpeed;

                        if (c1 == 0 && (speed < 0.15 || AngleBetweenSelfAndSpeed < Angle[90]))
                        {
                            SetMove(1, 1);
                            gogogo = true;
                        }
                        else
                        {
                            int c2 = CheckToBeWounded(self, -1);
                            // Назад
                            if (c2 == 0)
                            {
                                SetMove(-1, -1);
                                gogogo = true;
                            }
                            else
                            {
                                if (DistanseToBorder(self) < self.Width)
                                {
                                    if (!OutOfRange(FictiveTank(self.X + 20 * Math.Cos(self.Angle), self.Y + 20 * Math.Sin(self.Angle), 3452343), 0.85))
                                        SetMove(1, 1);
                                    else
                                        SetMove(-1, -1);
                                    gogogo = true;
                                }
                                // Если приходится ставиться под рикошет
                                else if (c1 == 2 || c2 == 2)
                                {
                                    SetMove(1, -1);
                                    gogogo = true;
                                }
                            }
                        }
                    }
                }
            }

            /*
            // Поиск тех кто направил на меня пушку
            int fireTo = -1;
            double mindist = 10000;
            for (int i = 0; i < world.Tanks.Length; i++)
            {
                if (!world.Tanks[i].IsTeammate && IsAlive(world.Tanks[i]))
                {
                    double angle = world.Tanks[i].GetTurretAngleTo(self);
                    if (Math.Abs(angle) < Angle[5])
                    {
                        double d = self.GetDistanceTo(world.Tanks[i]);
                        if (d < mindist)
                        {
                            mindist = d;
                            fireTo = i;
                        }
                    }
                }
            }
            if (fireTo != -1 && self.GetDistanceTo(world.Tanks[fireTo]) < self.Width * 5)
            {
                selectedTank = fireTo;
                goalFinded = true;
            }*/

            if (!gogogo && CountAlive() == 2 && bonusId != world.Bonuses.Length)
            {

                // Поиск тех кто направил пушку и стоит перпендикулярно мне
                for (int i = 0; i < world.Tanks.Length; i++)
                {
                    if (!world.Tanks[i].IsTeammate && IsAlive(world.Tanks[i]))
                    {
                        double AngleBetweenSelfAndHisTurret = Math.Abs(NormAngle(self.Angle - GetTurretAngle(world.Tanks[i])));
                        if (AngleBetweenSelfAndHisTurret > Angle[90])
                            AngleBetweenSelfAndHisTurret = Angle[180] - AngleBetweenSelfAndHisTurret;

                        // если он под углом меньше 30
                        if (AngleBetweenSelfAndHisTurret < Angle[30] && world.Tanks[i].GetTurretAngleTo(self) < Angle[20])
                        {
                            // Поворачиваемся перпендикулярно и отъезжаем
                            double an1 = self.Angle + Angle[90];
                            double an2 = self.Angle - Angle[90];
                            double X1 = self.X + 300 * Math.Cos(an1);
                            double Y1 = self.Y + 300 * Math.Sin(an1);
                            double X2 = self.X + 300 * Math.Cos(an2);
                            double Y2 = self.Y + 300 * Math.Sin(an2);
                            if (!OutOfRange(X1, Y1))
                            {
                                Go(self, X1, Y1);
                                /*xGoAway = X1;
                                yGoAway = Y1;
                                goAway = 50;*/
                            }
                            else if (!OutOfRange(X2, Y2))
                            {
                                Go(self, x2, y2);
                                /*xGoAway = X2;
                                yGoAway = Y2;
                                goAway = 50;*/
                            }
                        }
                    }
                }

            }

            if (End())
            {
                foreach (Tank t in world.Tanks)
                {
                    if (!t.IsTeammate && IsAlive(t))
                    {
                        Go(self, t.X, t.Y);
                        break;
                    }
                }
            }

            double Dist = self.GetDistanceTo(world.Tanks[selectedTank]);
            move.TurretTurn = self.GetTurretAngleTo(world.Tanks[selectedTank]);

            if (goalFinded && Hit(self, world.Tanks[selectedTank]))
            {
                double angle = Math.Abs(NormAngle(world.Tanks[selectedTank].Angle - NormAngle(self.GetTurretAngleTo(world.Tanks[selectedTank]) + self.Angle + self.TurretRelativeAngle)));
                if (angle > Angle[90])
                    angle = Angle[180] - angle;

                if (!(angle > Angle[60] && Dist > world.Height * 0.7) || noFire > 300)
                {
                    noFire = 0;
                    if (Dist < world.Width / 2 || (Dist < world.Height && angle < Angle[20]) || world.Tick > 4500)
                        move.FireType = FireType.PremiumPreferred;
                    else
                        move.FireType = FireType.Regular;
                }
                else
                {
                    noFire++;
                }
            }

            if (world.Tick < 200)
            {
                if (!selectedPoint)
                {
                    double minDist = 10000;
                    minX = 10000;
                    minY = 10000;
                    for (double x = world.Width * 0.03; x < world.Width; x += world.Width * 0.94)
                    {
                        for (double y = world.Height * 0.03; y < world.Height; y += world.Height * 0.94)
                        {
                            double d = self.GetDistanceTo(x, y);
                            if (d < minDist)
                            {
                                minDist = d;
                                minX = x;
                                minY = y;
                            }
                        }
                    }
                    selectedPoint = true;
                }
                Go(self, minX, minY);
            }

            if (world.Tick < start)
            {
                move.FireType = FireType.None;
            }
        }