// Анализ позиции 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; }
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; }