示例#1
0
 // Стоимость хода
 private int MoveCost(MyTrooper trooper)
 {
     if (trooper.Stance == TrooperStance.Prone) return m_game.ProneMoveCost;
     if (trooper.Stance == TrooperStance.Kneeling) return m_game.KneelingMoveCost;
     return m_game.StandingMoveCost;
 }
示例#2
0
        // Основной метод
        public void Move(Trooper self, World world, Game game, Move move)
        {
            if (self.ActionPoints == 0) return;
            cnt_invoke = 0;

            m_self = self;
            m_game = game;
            m_world = world;
            m_cells = world.Cells;

            // Определение игрока-цели
            Player nearToCentr = null;
            foreach (Player p in world.Players)
                if (p.Id != self.PlayerId &&
                    p.ApproximateX >= 0 &&
                    p.ApproximateY >= 0)
                    if (nearToCentr == null ||
                        FindNextStep(self.X, self.Y, nearToCentr.ApproximateX, nearToCentr.ApproximateY, 3).dist >
                        FindNextStep(self.X, self.Y, p.ApproximateX, p.ApproximateY, 3).dist
                    ) nearToCentr = p;
            if (nearToCentr != null)
            {
                targetX = nearToCentr.ApproximateX;
                targetY = nearToCentr.ApproximateY;
            }

            if (m_cellDangerous == null) CellDangerous();
            if (targetX == -1 && targetY == -1)
            {
                targetX = self.X;
                targetY = self.Y;
            }

            // Запрос цели
            const double stageDist = 2.5;
            if (self.GetDistanceTo(targetX, targetY) <= stageDist ||
                world.MoveIndex - moveWithoutEnemy >= 4)
            {
                bool CommanderAlive = false;
                foreach (Trooper tr in world.Troopers)
                    if (tr.IsTeammate && tr.Type == TrooperType.Commander)
                        CommanderAlive = true;
                if (!CommanderAlive)
                {
                    targetX = random.Next(world.Width);
                    targetY = random.Next(world.Height);
                    moveWithoutEnemy = world.MoveIndex;
                }
                else
                    if (self.Type == TrooperType.Commander &&
                        self.ActionPoints >= game.CommanderRequestEnemyDispositionCost)
                    {
                        move.Action = ActionType.RequestEnemyDisposition;
                        moveWithoutEnemy = world.MoveIndex;
                        return;
                    }
            }

            // Заполнение списка солдат, определение отсутствия врагов
            if (self.ActionPoints >= self.InitialActionPoints)
                m_troopers = new ArrayList();
            foreach (Trooper trooper in m_world.Troopers)
            {
                if (trooper.IsTeammate == false)
                    moveWithoutEnemy = m_world.MoveIndex;

                bool isExist = false;
                for (int i = 0; i < m_troopers.Count; i++)
                {
                    MyTrooper mt = (MyTrooper)m_troopers[i];
                    if (mt.Id == trooper.Id && mt.PlayerId == trooper.PlayerId)
                    {
                        isExist = true;
                        m_troopers[i] = new MyTrooper(trooper);
                        break;
                    }
                }
                if (!isExist) m_troopers.Add(new MyTrooper(trooper));
            }

            // Выбор оптимального действия
            Move m = FindNextMove(new MyTrooper(self), new ArrayList(m_world.Players), m_troopers, new ArrayList(m_world.Bonuses)).move;

            move.Action = m.Action;
            move.Direction = m.Direction;
            move.X = m.X;
            move.Y = m.Y;

            return;
        }
示例#3
0
        // Анализ позиции
        private double GetPositionValue(MyTrooper self, ArrayList players, ArrayList troopers, ArrayList bonuses)
        {
            double value = 0.0;

            double enemyDeath = 75.0;
            double enemyHitpoints = 1.0;
            double teamHitpoints = 2.5;

            double isHoldingFieldRation = 25.0;
            double isHoldingGrenade = 25.0;
            double isHoldingMedikit = 25.0;

            double canShootEnemy = 0;
            double canSeeEnemy = 0;
            double canBeShootingByEnemy = 20.0;
            double canBeSeeningByEnemy = 30.0;

            double distance = 0.75;
            double distanceTeam = 0.2;
            double danger = 0.001;

            // Бонусы солдата
            value += self.IsHoldingFieldRation ? isHoldingFieldRation : 0;
            value += self.IsHoldingGrenade ? isHoldingGrenade : 0;
            value += self.IsHoldingMedikit ? isHoldingMedikit : 0;

            // Взаиморасположение с другими солдатами
            foreach (MyTrooper trooper in troopers)
            {
                if (trooper.IsTeammate == false)
                {
                    // Смерть врага
                    value += trooper.Hitpoints <= 0 ? enemyDeath : 0;

                    // Видимость и возможность выстрела во врага
                    value += m_world.IsVisible(self.ShootingRange, self.X, self.Y, self.Stance, trooper.X, trooper.Y, trooper.Stance) ?
                        canShootEnemy : 0;
                    value += m_world.IsVisible(self.VisionRange, self.X, self.Y, self.Stance, trooper.X, trooper.Y, trooper.Stance) ?
                        canSeeEnemy : 0;

                    // Здоровье врагов
                    value -= trooper.Hitpoints * enemyHitpoints;

                    // Видимость и возможность выстрела врагом в солдата
                    value -= m_world.IsVisible(trooper.ShootingRange, trooper.X, trooper.Y, trooper.Stance, self.X, self.Y, self.Stance) ?
                        canBeShootingByEnemy * (2 - self.Hitpoints / self.MaximalHitpoints) : 0;
                    value -= m_world.IsVisible(trooper.VisionRange, trooper.X, trooper.Y, trooper.Stance, self.X, self.Y, self.Stance) ?
                        canBeSeeningByEnemy * (2 - self.Hitpoints / self.MaximalHitpoints) : 0;
                }
                if (trooper.IsTeammate == true)
                {
                    // Здоровье своих
                    value += trooper.Hitpoints * teamHitpoints;

                    // Опасная клетка
                    value -= m_cellDangerous[self.X][self.Y] * danger;

                    // Удаленность от своих
                    value -= distanceTeam * self.GetDistanceTo(trooper.X, trooper.Y);
                    value -= distanceTeam * FindNextStep(self.X, self.Y, trooper.X, trooper.Y, 5).dist;
                }
            }

            // Удаленность солдата от цели
            value -= distance * self.GetDistanceTo(targetX, targetY);
            value -= distance * FindNextStep(self.X, self.Y, targetX, targetY, 5).dist;

            return value;
        }
示例#4
0
        private MoveVal FindNextMove(MyTrooper self, ArrayList players, ArrayList troopers, ArrayList bonuses)
        {
            MoveVal mv;
            mv.val = (self.ActionPoints <= MoveCost(self)) ? GetPositionValue(self, players, troopers, bonuses) : -1000;
            mv.move = new Move();
            mv.move.Action = ActionType.EndTurn;

            if (cnt_invoke++ > 16000) return mv;

            int[] nearX = { 0, 0, 0, 1, -1 };
            int[] nearY = { 0, 1, -1, 0, 0 };
            Direction[] nearDir = { Direction.CurrentPoint, Direction.South, Direction.North, Direction.East, Direction.West };

            // 1. Eat Field Ration
            if (self.IsHoldingFieldRation &&
                self.ActionPoints + m_game.FieldRationBonusActionPoints <= self.InitialActionPoints &&
                self.ActionPoints >= m_game.FieldRationEatCost)
            {
                self.ActionPoints -= m_game.FieldRationEatCost - m_game.FieldRationBonusActionPoints;
                self.IsHoldingFieldRation = false;

                MoveVal next = FindNextMove(self, players, troopers, bonuses);
                if (mv.val < next.val)
                {
                    mv.move.Action = ActionType.EatFieldRation;
                    mv.move.Direction = Direction.CurrentPoint;
                    mv.val = next.val;
                }

                self.IsHoldingFieldRation = true;
                self.ActionPoints += m_game.FieldRationEatCost - m_game.FieldRationBonusActionPoints;
            }

            // 2. Throw Grenade
            if (self.IsHoldingGrenade)
                foreach (MyTrooper enemy in troopers)
                {
                    if (enemy.IsTeammate == true) continue;
                    for (int i = 0; i < 5; i++)
                        if (enemy.X + nearX[i] < m_world.Width &&
                            enemy.Y + nearY[i] < m_world.Height &&
                            enemy.X + nearX[i] >= 0 &&
                            enemy.Y + nearY[i] >= 0 &&
                            self.GetDistanceTo(enemy.X + nearX[i], enemy.Y + nearY[i]) <= m_game.GrenadeThrowRange &&
                            self.ActionPoints >= m_game.GrenadeThrowCost)
                        {
                            self.ActionPoints -= m_game.FieldMedicHealCost;
                            self.IsHoldingGrenade = false;
                            foreach (MyTrooper et in troopers)
                            {
                                if (et.GetDistanceTo(enemy.X + nearX[i], enemy.Y + nearY[i]) == 1)
                                    et.Hitpoints -= m_game.GrenadeCollateralDamage;
                                if (et.GetDistanceTo(enemy.X + nearX[i], enemy.Y + nearY[i]) == 0)
                                    et.Hitpoints -= m_game.GrenadeDirectDamage;
                            }

                            MoveVal next = FindNextMove(self, players, troopers, bonuses);
                            if (mv.val < next.val)
                            {
                                mv.move.Action = ActionType.ThrowGrenade;
                                mv.move.Direction = null;
                                mv.move.X = enemy.X + nearX[i];
                                mv.move.Y = enemy.Y + nearY[i];
                                mv.val = next.val;
                            }

                            self.IsHoldingGrenade = true;
                            self.ActionPoints += m_game.FieldMedicHealCost;
                            foreach (MyTrooper et in troopers)
                            {
                                if (et.GetDistanceTo(enemy.X + nearX[i], enemy.Y + nearY[i]) == 1)
                                    et.Hitpoints += m_game.GrenadeCollateralDamage;
                                if (et.GetDistanceTo(enemy.X + nearX[i], enemy.Y + nearY[i]) == 0)
                                    et.Hitpoints += m_game.GrenadeDirectDamage;
                            }
                        }
                }

            // 3. Medikit
            if (self.IsHoldingMedikit)
                for (int i = 0; i < 5; i++)
                    if (self.X + nearX[i] < m_world.Width &&
                        self.Y + nearY[i] < m_world.Height &&
                        self.X + nearX[i] >= 0 &&
                        self.Y + nearY[i] >= 0 &&
                        self.ActionPoints >= m_game.MedikitUseCost)
                        foreach (MyTrooper mt in troopers)
                            if (mt.IsTeammate &&
                                mt.X == self.X + nearX[i] &&
                                mt.Y == self.Y + nearY[i] &&
                                mt.MaximalHitpoints - mt.Hitpoints >= (i == 0 ? m_game.MedikitHealSelfBonusHitpoints : m_game.MedikitBonusHitpoints))
                            {
                                self.ActionPoints -= m_game.MedikitUseCost;
                                mt.Hitpoints += (i == 0 ? m_game.MedikitHealSelfBonusHitpoints : m_game.MedikitBonusHitpoints);
                                self.IsHoldingMedikit = false;

                                MoveVal next = FindNextMove(self, players, troopers, bonuses);
                                if (mv.val < next.val)
                                {
                                    mv.move.Action = ActionType.UseMedikit;
                                    mv.move.Direction = nearDir[i];
                                    mv.val = next.val;
                                }

                                self.IsHoldingMedikit = true;
                                self.ActionPoints += m_game.MedikitUseCost;
                                mt.Hitpoints -= (i == 0 ? m_game.MedikitHealSelfBonusHitpoints : m_game.MedikitBonusHitpoints);
                            }

            // 4. Move
            int moveCost = MoveCost(self);
            for (int i = 1; i < 5; i++)
                if (self.X + nearX[i] < m_world.Width &&
                    self.Y + nearY[i] < m_world.Height &&
                    self.X + nearX[i] >= 0 &&
                    self.Y + nearY[i] >= 0 &&
                    self.ActionPoints >= moveCost &&
                    m_cells[self.X + nearX[i]][self.Y + nearY[i]] == CellType.Free)
                {
                    bool isTrooper = false;
                    foreach (MyTrooper trooper in m_troopers)
                        if (self.X + nearX[i] == trooper.X &&
                            self.Y + nearY[i] == trooper.Y) isTrooper = true;
                    if (isTrooper) continue;

                    self.ActionPoints -= moveCost;
                    self.X += nearX[i];
                    self.Y += nearY[i];

                    Bonus bonus = null;
                    foreach (Bonus b in bonuses)
                        if (b != null &&
                            b.X == self.X &&
                            b.Y == self.Y &&
                            (!self.IsHoldingFieldRation && b.Type == BonusType.FieldRation ||
                             !self.IsHoldingGrenade && b.Type == BonusType.Grenade ||
                             !self.IsHoldingMedikit && b.Type == BonusType.Medikit))
                            bonus = b;
                    if (bonus != null)
                    {
                        bonuses.Remove(bonus);
                        if (bonus.Type == BonusType.FieldRation) self.IsHoldingFieldRation = true;
                        if (bonus.Type == BonusType.Grenade) self.IsHoldingGrenade = true;
                        if (bonus.Type == BonusType.Medikit) self.IsHoldingMedikit = true;
                    }

                    MoveVal next = FindNextMove(self, players, troopers, bonuses);
                    if (mv.val < next.val)
                    {
                        mv.move.Action = ActionType.Move;
                        mv.move.Direction = nearDir[i];
                        mv.val = next.val;
                    }

                    if (bonus != null)
                    {
                        bonuses.Add(bonus);
                        if (bonus.Type == BonusType.FieldRation) self.IsHoldingFieldRation = false;
                        if (bonus.Type == BonusType.Grenade) self.IsHoldingGrenade = false;
                        if (bonus.Type == BonusType.Medikit) self.IsHoldingMedikit = false;
                    }
                    self.X -= nearX[i];
                    self.Y -= nearY[i];
                    self.ActionPoints += MoveCost(self);
                }

            // 5. Lower Stance
            if (self.Stance != TrooperStance.Prone &&
                self.ActionPoints >= m_game.StanceChangeCost)
            {
                self.ActionPoints -= m_game.StanceChangeCost;
                if (self.Stance == TrooperStance.Standing) self.Stance = TrooperStance.Kneeling;
                else
                    if (self.Stance == TrooperStance.Kneeling) self.Stance = TrooperStance.Prone;

                MoveVal next = FindNextMove(self, players, troopers, bonuses);
                if (mv.val < next.val)
                {
                    mv.move.Action = ActionType.LowerStance;
                    mv.move.Direction = Direction.CurrentPoint;
                    mv.val = next.val;
                }

                self.ActionPoints += m_game.StanceChangeCost;
                if (self.Stance == TrooperStance.Kneeling) self.Stance = TrooperStance.Standing;
                else
                    if (self.Stance == TrooperStance.Prone) self.Stance = TrooperStance.Kneeling;
            }

            // 6. Raise Stance
            if (self.Stance != TrooperStance.Standing &&
                self.ActionPoints >= m_game.StanceChangeCost)
            {
                self.ActionPoints -= m_game.StanceChangeCost;
                if (self.Stance == TrooperStance.Kneeling) self.Stance = TrooperStance.Standing;
                else
                    if (self.Stance == TrooperStance.Prone) self.Stance = TrooperStance.Kneeling;

                MoveVal next = FindNextMove(self, players, troopers, bonuses);
                if (mv.val < next.val)
                {
                    mv.move.Action = ActionType.RaiseStance;
                    mv.move.Direction = Direction.CurrentPoint;
                    mv.val = next.val;
                }

                self.ActionPoints += m_game.StanceChangeCost;
                if (self.Stance == TrooperStance.Standing) self.Stance = TrooperStance.Kneeling;
                else
                    if (self.Stance == TrooperStance.Kneeling) self.Stance = TrooperStance.Prone;
            }

            // 7. Heal
            for (int i = 0; i < 5; i++)
                if (self.X + nearX[i] < m_world.Width &&
                    self.Y + nearY[i] < m_world.Height &&
                    self.X + nearX[i] >= 0 &&
                    self.Y + nearY[i] >= 0 &&
                    self.Type == TrooperType.FieldMedic &&
                    self.ActionPoints >= m_game.FieldMedicHealCost)
                    foreach (MyTrooper mt in troopers)
                        if (mt.IsTeammate == true &&
                            mt.X == self.X + nearX[i] &&
                            mt.Y == self.Y + nearY[i] &&
                            mt.MaximalHitpoints - mt.Hitpoints >= (i == 0 ? m_game.FieldMedicHealSelfBonusHitpoints : m_game.FieldMedicHealBonusHitpoints))
                        {
                            self.ActionPoints -= m_game.FieldMedicHealCost;
                            mt.Hitpoints += (i == 0 ? m_game.FieldMedicHealSelfBonusHitpoints : m_game.FieldMedicHealBonusHitpoints);

                            MoveVal next = FindNextMove(self, players, troopers, bonuses);
                            if (mv.val < next.val)
                            {
                                mv.move.Action = ActionType.Heal;
                                mv.move.Direction = nearDir[i];
                                mv.val = next.val;
                            }

                            self.ActionPoints += m_game.FieldMedicHealCost;
                            mt.Hitpoints -= (i == 0 ? m_game.FieldMedicHealSelfBonusHitpoints : m_game.FieldMedicHealBonusHitpoints);
                        }

            // 8. Shoot
            foreach (MyTrooper enemy in troopers)
            {
                if (enemy.IsTeammate == true) continue;
                if (self.ActionPoints >= self.ShootCost &&
                    m_world.IsVisible(self.ShootingRange, self.X, self.Y, self.Stance, enemy.X, enemy.Y, enemy.Stance))
                {
                    self.ActionPoints -= self.ShootCost;
                    enemy.Hitpoints -= self.Damage;

                    MoveVal next = FindNextMove(self, players, troopers, bonuses);
                    if (mv.val < next.val)
                    {
                        mv.move.Action = ActionType.Shoot;
                        mv.move.Direction = null;
                        mv.move.X = enemy.X;
                        mv.move.Y = enemy.Y;
                        mv.val = next.val;
                    }

                    enemy.Hitpoints += self.Damage;
                    self.ActionPoints += self.ShootCost;
                }
            }

            return mv;
        }