Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Linq;
- using System.Collections.Generic;
- using Com.CodeGame.CodeTroopers2013.DevKit.CSharpCgdk.Model;
- namespace Com.CodeGame.CodeTroopers2013.DevKit.CSharpCgdk
- {
- public sealed class MyStrategy : IStrategy
- {
- private Trooper _self;
- private static World _world;
- private static Game _game;
- private Move _move;
- private const int RegionSize = 6;
- private static readonly Random Rnd = new Random();
- private Region _oldRegion = Region.Unknown,
- _targetRegion = Region.Center;
- private static int _stepsWithoutEnemies;
- private static int _dispositionRequested;
- private const int MaxLeaderDistance = 3;
- private int[,,] _dangerField;
- private enum Region
- {
- Unknown, NW, NE, SW, SE, Center
- }
- private static readonly List<Region> RandomRegions = new List<Region>
- {
- Region.NE,
- Region.NW,
- Region.SE,
- Region.SW,
- Region.Center
- };
- private Region GetRandomRegion()
- {
- if (RandomRegions.Count == 0)
- {
- return Rnd.Next(2) > 0
- ? (Rnd.Next(2) > 0 ? Region.NW : Region.NE)
- : (Rnd.Next(2) > 0 ? Region.SE : Region.SW);
- }
- int idx = Rnd.Next(RandomRegions.Count);
- Region region = RandomRegions[idx];
- RandomRegions.RemoveAt(idx);
- return region;
- }
- private IEnumerable<Point> FindEmptyPointsForRegion(Region region)
- {
- if (region == Region.Unknown)
- yield break;
- Trooper leader = Leader;
- switch (region)
- {
- case Region.NW:
- for (int j = 0; j < RegionSize; ++j)
- for (int i = 0; i < RegionSize; ++i)
- if (_world.Cells[i][j] == CellType.Free && !_world.Troopers.Any(t => t.X == i && t.Y == j))
- if (FindPathDistance(new Point(leader.X, leader.Y), new Point(i, j), false, false) > 2)
- yield return new Point(i, j);
- break;
- case Region.NE:
- for (int j = 0; j < RegionSize; ++j)
- for (int i = _world.Width - 1; i >= _world.Width - RegionSize; --i)
- if (_world.Cells[i][j] == CellType.Free && !_world.Troopers.Any(t => t.X == i && t.Y == j))
- if (FindPathDistance(new Point(leader.X, leader.Y), new Point(i, j), false, false) > 2)
- yield return new Point(i, j);
- break;
- case Region.SW:
- for (int j = _world.Height - 1; j >= _world.Height - RegionSize; --j)
- for (int i = 0; i < RegionSize; ++i)
- if (_world.Cells[i][j] == CellType.Free && !_world.Troopers.Any(t => t.X == i && t.Y == j))
- if (FindPathDistance(new Point(leader.X, leader.Y), new Point(i, j), false, false) > 2)
- yield return new Point(i, j);
- break;
- case Region.SE:
- for (int j = _world.Height - 1; j >= _world.Height - RegionSize; --j)
- for (int i = _world.Width - 1; i >= _world.Width - RegionSize; --i)
- if (_world.Cells[i][j] == CellType.Free && !_world.Troopers.Any(t => t.X == i && t.Y == j))
- if (FindPathDistance(new Point(leader.X, leader.Y), new Point(i, j), false, false) > 2)
- yield return new Point(i, j);
- break;
- case Region.Center:
- for (int j = _world.Height / 2 - RegionSize / 2; j < _world.Height / 2 + RegionSize / 2; ++j)
- for (int i = _world.Width / 2 - RegionSize / 2; i < _world.Width / 2 + RegionSize / 2; ++i)
- if (_world.Cells[i][j] == CellType.Free && !_world.Troopers.Any(t => t.X == i && t.Y == j))
- if (FindPathDistance(new Point(leader.X, leader.Y), new Point(i, j), false, false) > 2)
- yield return new Point(i, j);
- break;
- }
- }
- private Region GetRegion(Point pt)
- {
- if (pt.Y < RegionSize && pt.X < RegionSize) return Region.NW;
- if (pt.Y < RegionSize && pt.X >= _world.Width - RegionSize) return Region.NE;
- if (pt.Y >= _world.Height - RegionSize && pt.X < RegionSize) return Region.SW;
- if (pt.Y >= _world.Height - RegionSize && pt.X >= _world.Width - RegionSize) return Region.SE;
- if (pt.Y >= _world.Height / 2 - RegionSize / 2 && pt.Y < _world.Height / 2 + RegionSize / 2 &&
- pt.X >= _world.Width / 2 - RegionSize / 2 && pt.X < _world.Width / 2 + RegionSize / 2) return Region.Center;
- return Region.Unknown;
- }
- private Region GetCurrentRegion()
- {
- return GetRegion(new Point(_self.X, _self.Y));
- }
- private struct Point
- {
- public Point(int x, int y)
- {
- X = x;
- Y = y;
- }
- public readonly int X, Y;
- public bool InWorld
- {
- get { return X >= 0 && Y >= 0 && X < _world.Width && Y < _world.Height; }
- }
- public static bool operator ==(Point pt0, Point pt1)
- {
- return pt0.X == pt1.X && pt0.Y == pt1.Y;
- }
- public static bool operator !=(Point pt0, Point pt1)
- {
- return !(pt0 == pt1);
- }
- public override bool Equals(object o)
- {
- return o is Point && ((Point)o) == this;
- }
- public override int GetHashCode()
- {
- return X.GetHashCode() ^ Y.GetHashCode();
- }
- }
- public Trooper Leader
- {
- get
- {
- List<TrooperType> LeadershipRating = null;
- switch (_self.Type)
- {
- case TrooperType.Sniper:
- LeadershipRating = new List<TrooperType>
- {
- TrooperType.Sniper,
- TrooperType.Soldier,
- TrooperType.Commander,
- TrooperType.Scout,
- TrooperType.FieldMedic
- };
- break;
- case TrooperType.Soldier:
- LeadershipRating = new List<TrooperType>
- {
- TrooperType.Soldier,
- TrooperType.Sniper,
- TrooperType.Commander,
- TrooperType.Scout,
- TrooperType.FieldMedic
- };
- break;
- case TrooperType.Commander:
- LeadershipRating = new List<TrooperType>
- {
- TrooperType.Soldier,
- TrooperType.Sniper,
- TrooperType.Commander,
- TrooperType.Scout,
- TrooperType.FieldMedic
- };
- break;
- case TrooperType.Scout:
- LeadershipRating = new List<TrooperType>
- {
- TrooperType.Soldier,
- TrooperType.Sniper,
- TrooperType.Commander,
- TrooperType.Scout,
- TrooperType.FieldMedic
- };
- break;
- case TrooperType.FieldMedic:
- LeadershipRating = new List<TrooperType>
- {
- TrooperType.Sniper,
- TrooperType.Soldier,
- TrooperType.Commander,
- TrooperType.Scout,
- TrooperType.FieldMedic
- };
- break;
- }
- return Teammates.First(trooper => trooper.Type == Teammates.Aggregate(
- TrooperType.FieldMedic,
- (acc, curr) => LeadershipRating.IndexOf(curr.Type) < LeadershipRating.IndexOf(acc) ? curr.Type : acc));
- }
- }
- private Trooper Medic
- {
- get { return Teammates.FirstOrDefault(trooper => trooper.Type == TrooperType.FieldMedic); }
- }
- private IEnumerable<Trooper> Wounded
- {
- get
- {
- return Teammates
- .Where(trooper => trooper.Hitpoints < trooper.MaximalHitpoints)
- .OrderBy(trooper => trooper.Hitpoints);
- }
- }
- private IEnumerable<Trooper> Teammates
- {
- get { return _world.Troopers.Where(trooper => trooper.IsTeammate); }
- }
- private IEnumerable<Trooper> Enemies
- {
- get
- {
- return _world
- .Troopers
- .Where(trooper => !trooper.IsTeammate)
- .OrderBy(trooper => trooper.Type == TrooperType.Sniper ? 0 : 1)
- .ThenBy(trooper => trooper.Type == TrooperType.FieldMedic ? 0 : 1);
- }
- }
- private IEnumerable<Trooper> GetShootableEnemies(TrooperStance? selfStance)
- {
- return Enemies
- .Where(enemy => _world.IsVisible(
- Math.Min(_self.ShootingRange, _self.VisionRange),
- _self.X, _self.Y, selfStance ?? _self.Stance,
- enemy.X, enemy.Y, enemy.Stance))
- .OrderBy(enemy => enemy.Hitpoints);
- }
- private IEnumerable<Trooper> GetKillableEnemies(TrooperStance? selfStance)
- {
- return GetShootableEnemies(selfStance)
- .Where(enemy => enemy.Hitpoints <= _self.ActionPoints / _self.ShootCost * Damage);
- }
- private bool CanShoot
- {
- get { return _self.ActionPoints >= _self.ShootCost; }
- }
- private int MoveCost
- {
- get
- {
- switch (_self.Stance)
- {
- case TrooperStance.Standing:
- return _game.StandingMoveCost;
- case TrooperStance.Kneeling:
- return _game.KneelingMoveCost;
- case TrooperStance.Prone:
- return _game.ProneMoveCost;
- }
- return int.MaxValue;
- }
- }
- private int Damage
- {
- get
- {
- switch (_self.Stance)
- {
- case TrooperStance.Standing:
- return _self.StandingDamage;
- case TrooperStance.Kneeling:
- return _self.KneelingDamage;
- case TrooperStance.Prone:
- return _self.ProneDamage;
- }
- return int.MaxValue;
- }
- }
- private bool CanMove
- {
- get { return _self.ActionPoints >= MoveCost; }
- }
- private static Direction PointsToDirection(int fromX, int fromY, int targetX, int targetY)
- {
- if (targetY == fromY - 1) return Direction.North;
- if (targetY == fromY + 1) return Direction.South;
- if (targetX == fromX - 1) return Direction.West;
- if (targetX == fromX + 1) return Direction.East;
- return Direction.CurrentPoint;
- }
- private IEnumerable<Tuple<Bonus, int, Direction>> GetBonuses(int maxDistance)
- {
- return _world.Bonuses
- .Select(bonus => new {bonus, dist = FindPathTo(new Point(bonus.X, bonus.Y), false).ToArray() })
- .Where(bonus => bonus.dist != null && bonus.dist.Length <= maxDistance && bonus.dist.Length > 1)
- .OrderBy(bonus => bonus.dist.Length)
- .Select(bonus => new Tuple<Bonus, int, Direction>(
- bonus.bonus,
- bonus.dist.Length,
- PointsToDirection(_self.X, _self.Y, bonus.dist[1].X, bonus.dist[1].Y)));
- }
- private int FindPathDistance(Point from, Point to, bool transparentTeammates, bool transparentWorld)
- {
- if (!from.InWorld || !to.InWorld)
- return int.MaxValue;
- var arr = new int[_world.Width, _world.Height];
- if (!transparentWorld)
- for (int i = 0; i < _world.Width; ++i)
- for (int j = 0; j < _world.Height; ++j)
- if (_world.Cells[i][j] != CellType.Free)
- arr[i, j] = -1;
- if (transparentTeammates)
- {
- foreach (Trooper trooper in Enemies)
- if (trooper.X != to.X || trooper.Y != to.Y)
- arr[trooper.X, trooper.Y] = -1;
- }
- else
- {
- foreach (Trooper trooper in _world.Troopers)
- if (trooper.X != to.X || trooper.Y != to.Y)
- arr[trooper.X, trooper.Y] = -1;
- }
- int currStep = 1;
- int worldSize = _world.Width * _world.Height;
- var list = new List<Point>(worldSize);
- arr[from.X, from.Y] = currStep;
- list.Add(from);
- if (arr[from.X, from.Y] == -1 || arr[to.X, to.Y] == -1)
- return int.MaxValue;
- while (list.Count > 0)
- {
- var tmp = new List<Point>(worldSize);
- int nextStep = currStep + 1;
- foreach (Point pt in list)
- {
- if (pt == to)
- return currStep;
- if (pt.X > 0 && arr[pt.X - 1, pt.Y] == 0)
- {
- arr[pt.X - 1, pt.Y] = nextStep;
- tmp.Add(new Point(pt.X - 1, pt.Y));
- }
- if (pt.Y > 0 && arr[pt.X, pt.Y - 1] == 0)
- {
- arr[pt.X, pt.Y - 1] = nextStep;
- tmp.Add(new Point(pt.X, pt.Y - 1));
- }
- if (pt.X < _world.Width - 1 && arr[pt.X + 1, pt.Y] == 0)
- {
- arr[pt.X + 1, pt.Y] = nextStep;
- tmp.Add(new Point(pt.X + 1, pt.Y));
- }
- if (pt.Y < _world.Height - 1 && arr[pt.X, pt.Y + 1] == 0)
- {
- arr[pt.X, pt.Y + 1] = nextStep;
- tmp.Add(new Point(pt.X, pt.Y + 1));
- }
- }
- currStep = nextStep;
- list = tmp;
- }
- return int.MaxValue;
- }
- private IEnumerable<Point> FindPath(Point from, Point to, bool transparentTeammates)
- {
- if (!from.InWorld || !to.InWorld)
- yield break;
- var arr = new int[_world.Width, _world.Height];
- for (int i = 0; i < _world.Width; ++i)
- for (int j = 0; j < _world.Height; ++j)
- if (_world.Cells[i][j] != CellType.Free)
- arr[i, j] = -1;
- if (transparentTeammates)
- {
- foreach (Trooper trooper in Enemies)
- if (trooper.X != to.X || trooper.Y != to.Y)
- arr[trooper.X, trooper.Y] = -1;
- }
- else
- {
- foreach (Trooper trooper in _world.Troopers)
- if (trooper.X != to.X || trooper.Y != to.Y)
- arr[trooper.X, trooper.Y] = -1;
- }
- int currStep = 1, nextStep = 2;
- int worldSize = _world.Width * _world.Height;
- var list = new List<Point>(worldSize);
- arr[from.X, from.Y] = currStep;
- list.Add(from);
- if (arr[from.X, from.Y] == -1 || arr[to.X, to.Y] == -1)
- yield break;
- while (list.Count > 0)
- {
- var tmp = new List<Point>(worldSize);
- nextStep = currStep + 1;
- foreach (Point pt in list)
- {
- if (pt == to)
- {
- tmp.Clear();
- --nextStep;
- break;
- }
- foreach (Point point in GetCross(pt, false))
- {
- if (point.InWorld && arr[point.X, point.Y] == 0)
- {
- arr[point.X, point.Y] = nextStep;
- tmp.Add(point);
- }
- }
- }
- currStep = nextStep;
- list = tmp;
- }
- var path = new List<Point>(nextStep);
- int x = to.X;
- int y = to.Y;
- path.Add(to);
- while (currStep != 1)
- {
- int prevStep = currStep - 1;
- if (!GetCross(new Point(x, y), false).Any(pt =>
- {
- if (pt.InWorld && arr[pt.X, pt.Y] == prevStep)
- {
- path.Add(pt);
- x = pt.X;
- y = pt.Y;
- --currStep;
- return true;
- }
- return false;
- })) break;
- }
- if (currStep != 1)
- yield break;
- for (int i = path.Count - 1; i >= 0; --i)
- yield return path[i];
- }
- private IEnumerable<Point> FindPathTo(Point pt, bool transparentTeammates)
- {
- return FindPath(new Point(_self.X, _self.Y), pt, transparentTeammates);
- }
- private IEnumerable<IEnumerable<Point>> PathToEnemies
- {
- get { return Enemies.Select(enemy => FindPathTo(new Point(enemy.X, enemy.Y), false)); }
- }
- private int CellDangerous(Point pt, TrooperStance trooperStance)
- {
- if (!pt.InWorld)
- return 0;
- if (_dangerField != null)
- return _dangerField[pt.X, pt.Y, (int)trooperStance];
- int dangerous = 0;
- foreach (Trooper enemy in Enemies)
- {
- if (_world.IsVisible(
- Math.Min(enemy.ShootingRange, enemy.VisionRange),
- enemy.X, enemy.Y, enemy.Stance,
- pt.X, pt.Y, trooperStance))
- {
- dangerous += enemy.GetDamage(enemy.Stance);
- if (enemy.IsHoldingGrenade && enemy.GetDistanceTo(_self) <= _game.GrenadeThrowRange)
- dangerous += _game.GrenadeDirectDamage;
- }
- }
- return dangerous;
- }
- private IEnumerable<Point> GetCross(Point pt, bool withCentral)
- {
- List<Point> list;
- if (withCentral)
- list = new List<Point>
- {
- new Point(pt.X, pt.Y),
- new Point(pt.X - 1, pt.Y),
- new Point(pt.X + 1, pt.Y),
- new Point(pt.X, pt.Y - 1),
- new Point(pt.X, pt.Y + 1)
- };
- else
- list = new List<Point>
- {
- new Point(pt.X - 1, pt.Y),
- new Point(pt.X + 1, pt.Y),
- new Point(pt.X, pt.Y - 1),
- new Point(pt.X, pt.Y + 1)
- };
- var arr = new Point[list.Count];
- for (int i = 0; i < arr.Length; ++i)
- {
- int idx = Rnd.Next(list.Count);
- arr[i] = list[idx];
- list.RemoveAt(idx);
- }
- return arr;
- }
- private IEnumerable<Point> GetValidCross(Point pt, bool withCentral)
- {
- return GetCross(pt, withCentral).Where(point => point.InWorld).ToArray();
- }
- private bool IsUnitNear(Trooper trooper)
- {
- return trooper != null &&
- GetValidCross(new Point(_self.X, _self.Y), true).Any(pt => pt.X == trooper.X && pt.Y == trooper.Y);
- }
- private bool IsBlockedCross(Point point, IEnumerable<Point> additionalPoints)
- {
- return GetCross(point, false)
- .All(pt => !pt.InWorld ||
- _world.Troopers.Any(trooper => trooper.X == pt.X && trooper.Y == pt.Y) ||
- _world.Cells[pt.X][pt.Y] != CellType.Free ||
- additionalPoints.Any(additionalPoint => additionalPoint == pt));
- }
- private bool TryGetBonusIfItNear()
- {
- int bonusDist = _self.ActionPoints / MoveCost + 1;
- Trooper leader = Leader;
- foreach (Direction moveToBonus in GetBonuses(bonusDist)
- .Where(bonus => CellDangerous(new Point(bonus.Item1.X, bonus.Item1.Y), _self.Stance) == 0)
- .Where(bonus => FindPathDistance(
- new Point(leader.X, leader.Y),
- new Point(bonus.Item1.X, bonus.Item1.Y),
- true, false) <= _self.InitialActionPoints / MoveCost)
- .Where(bonus => bonus.Item1.Type == BonusType.FieldRation && !_self.IsHoldingFieldRation ||
- bonus.Item1.Type == BonusType.Grenade && !_self.IsHoldingGrenade ||
- bonus.Item1.Type == BonusType.Medikit && !_self.IsHoldingMedikit)
- .Select(bonus => bonus.Item3))
- {
- _move.Direction = moveToBonus;
- _move.Action = ActionType.Move;
- return true;
- }
- return false;
- }
- private bool TryKillWithGranade()
- {
- if (_self.IsHoldingGrenade && _self.ActionPoints >= _game.GrenadeThrowCost)
- {
- foreach (Trooper enemy in Enemies.Where(enemy => _self.GetDistanceTo(enemy) <= _game.GrenadeThrowRange &&
- enemy.Hitpoints <= _game.GrenadeDirectDamage))
- {
- _move.X = enemy.X;
- _move.Y = enemy.Y;
- _move.Action = ActionType.ThrowGrenade;
- return true;
- }
- }
- return false;
- }
- private bool TryKillEnemy()
- {
- if (CanShoot)
- {
- foreach (Trooper enemy in GetKillableEnemies(null))
- {
- _move.X = enemy.X;
- _move.Y = enemy.Y;
- _move.Action = ActionType.Shoot;
- return true;
- }
- }
- return false;
- }
- private bool TryShootToEnemy()
- {
- if (CanShoot)
- {
- foreach (Trooper enemy in GetShootableEnemies(null))
- {
- _move.X = enemy.X;
- _move.Y = enemy.Y;
- _move.Action = ActionType.Shoot;
- return true;
- }
- }
- return false;
- }
- private bool TryHealHimself()
- {
- if (_self.Type == TrooperType.FieldMedic &&
- _self.Hitpoints < _self.MaximalHitpoints &&
- _self.ActionPoints >= _game.FieldMedicHealCost)
- {
- _move.X = _self.X;
- _move.Y = _self.Y;
- _move.Action = ActionType.Heal;
- return true;
- }
- return false;
- }
- private bool TryHealTeammate()
- {
- if (_self.Type == TrooperType.FieldMedic)
- {
- foreach (Trooper wounded in Wounded)
- {
- Point[] pathTo = FindPathTo(new Point(wounded.X, wounded.Y), false).ToArray();
- if (pathTo.Length == 2)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pathTo[1].X, pathTo[1].Y);
- _move.Action = ActionType.Heal;
- return true;
- }
- }
- if (CanMove)
- {
- foreach (Trooper wounded in Wounded)
- {
- Point[] pathTo = FindPathTo(new Point(wounded.X, wounded.Y), false).ToArray();
- if (pathTo.Length == 2)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pathTo[1].X, pathTo[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- }
- }
- return false;
- }
- private IEnumerable<Tuple<int, int, int>> WhereICanGo(int maxSteps)
- {
- for (int i = _self.X - maxSteps; i <= _self.X + maxSteps; ++i)
- for (int j = _self.Y - maxSteps; j <= _self.Y + maxSteps; ++j)
- if (i >= 0 && j >= 0 && i < _world.Width && j < _world.Height)
- if (_world.Cells[i][j] == CellType.Free && _world.Troopers.Any(t => t.X != i || t.Y != j))
- {
- Point[] path = FindPathTo(new Point(i, j), false).ToArray();
- if (path.Length > 1 && path.Length - 1 <= maxSteps)
- {
- Point coords = path[path.Length - 1];
- yield return new Tuple<int, int, int>(coords.X, coords.Y, path.Length);
- }
- }
- }
- private bool TryMoveToThrowGranade()
- {
- if (_self.IsHoldingGrenade && _self.ActionPoints >= _game.GrenadeThrowCost)
- {
- int steps = (_self.ActionPoints - _game.GrenadeThrowCost) / MoveCost;
- foreach (Tuple<int, int, int> go in WhereICanGo(steps)
- .OrderBy(target => target.Item3)
- .Where(target => Enemies.Any(enemy => enemy.GetDistanceTo(target.Item1, target.Item2) <= _game.GrenadeThrowRange)))
- {
- Point[] path = FindPathTo(new Point(go.Item1, go.Item2), false).ToArray();
- if (path.Length > 1)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, path[1].X, path[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- }
- return false;
- }
- private bool TryMoveToKillWithGranade()
- {
- if (CanMove && _self.IsHoldingGrenade && _self.ActionPoints >= _game.GrenadeThrowCost)
- {
- int steps = (_self.ActionPoints - _game.GrenadeThrowCost) / MoveCost;
- foreach (Tuple<int, int, int> go in WhereICanGo(steps)
- .Where(target => Enemies.Any(enemy =>
- enemy.GetDistanceTo(target.Item1, target.Item2) <= _game.GrenadeThrowRange &&
- enemy.Hitpoints <= _game.GrenadeDirectDamage))
- .OrderBy(target => CellDangerous(new Point(target.Item1, target.Item2), _self.Stance)))
- {
- Point[] path = FindPathTo(new Point(go.Item1, go.Item2), false).ToArray();
- if (path.Length > 1)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, path[1].X, path[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- }
- return false;
- }
- private bool TryMoveToKillEnemy()
- {
- if (CanMove)
- {
- int steps = _self.ActionPoints / MoveCost;
- foreach (Tuple<int, int, int> go in WhereICanGo(steps)
- .OrderBy(target => target.Item3)
- .Where(target => Enemies.OrderByDescending(enemy => enemy.Hitpoints).Any(enemy =>
- _world.IsVisible(
- Math.Min(_self.ShootingRange, _self.VisionRange),
- target.Item1, target.Item2, _self.Stance,
- enemy.X, enemy.Y, enemy.Stance) &&
- enemy.Hitpoints <= Damage * (steps - (target.Item3 - 1)))))
- {
- Point[] path = FindPathTo(new Point(go.Item1, go.Item2), false).ToArray();
- if (path.Length > 1)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, path[1].X, path[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- }
- return false;
- }
- private bool TryThrowGranade()
- {
- if (_self.IsHoldingGrenade && _self.ActionPoints >= _game.GrenadeThrowCost)
- {
- foreach (Trooper enemy in Enemies.Where(e => _self.GetDistanceTo(e) <= _game.GrenadeThrowRange))
- {
- _move.X = enemy.X;
- _move.Y = enemy.Y;
- _move.Action = ActionType.ThrowGrenade;
- return true;
- }
- }
- return false;
- }
- private bool TryUseMedikitOnOther()
- {
- if (_self.IsHoldingMedikit && _self.ActionPoints >= _game.MedikitUseCost)
- {
- Trooper[] wounded = Wounded.ToArray();
- if (wounded.Length > 0)
- {
- foreach (Trooper woundedTrooper in wounded)
- {
- Point[] pathTo = FindPathTo(new Point(woundedTrooper.X, woundedTrooper.Y), false).ToArray();
- if (pathTo.Length > 2)
- {
- if (CanMove)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pathTo[1].X, pathTo[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- else if (pathTo.Length == 2)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pathTo[1].X, pathTo[1].Y);
- _move.Action = ActionType.UseMedikit;
- return true;
- }
- }
- }
- }
- return false;
- }
- private bool TryUseMedikitOnHimself()
- {
- if (_self.IsHoldingMedikit &&
- _self.Hitpoints <= _self.MaximalHitpoints - _game.MedikitHealSelfBonusHitpoints &&
- _self.ActionPoints >= _game.MedikitUseCost)
- {
- _move.X = _self.X;
- _move.Y = _self.Y;
- _move.Action = ActionType.UseMedikit;
- return true;
- }
- return false;
- }
- private bool TryEatFieldRation()
- {
- if (_self.IsHoldingFieldRation &&
- _self.ActionPoints <= _self.InitialActionPoints - _game.FieldRationBonusActionPoints &&
- _self.ActionPoints >= _game.FieldRationEatCost)
- {
- _move.Action = ActionType.EatFieldRation;
- return true;
- }
- return false;
- }
- private bool TryMovingToEnemy()
- {
- return CanMove && PathToEnemies.Select(p => p.ToArray()).Where(p => p.Length > 2).OrderBy(p => p.Length).Any(path =>
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, path[1].X, path[1].Y);
- _move.Action = ActionType.Move;
- return true;
- });
- }
- private bool TryMovingToMedicIfLowLife()
- {
- if (CanMove && _self.Hitpoints <= _self.MaximalHitpoints / 2)
- {
- Trooper medic = Medic;
- if (medic != null && !IsUnitNear(medic))
- {
- return FindPathTo(new Point(medic.X, medic.Y), false).Skip(1).Any(pt =>
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pt.X, pt.Y);
- _move.Action = ActionType.Move;
- return true;
- });
- }
- }
- return false;
- }
- private bool TryMovingToLeader()
- {
- Trooper leader = Leader;
- if (leader == null)
- return false;
- if (leader.Type == _self.Type)
- return false;
- if (CanMove && !IsUnitNear(leader))
- {
- Point[] pts = FindPathTo(new Point(leader.X, leader.Y), false).ToArray();
- if (pts.Length > 1 && !IsBlockedCross(new Point(leader.X, leader.Y), new[] { pts[1] }) /* && pts.Length < 10 */ /* ? */)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pts[1].X, pts[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- pts = FindPathTo(new Point(leader.X, leader.Y), true).ToArray();
- if (pts.Length > 1 && !_world.Troopers.Any(t => t.X == pts[1].X && t.Y == pts[1].Y) && !IsBlockedCross(new Point(leader.X, leader.Y), new[] { pts[1] }))
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pts[1].X, pts[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- return false;
- }
- private void UpdateRegion()
- {
- Region currentRegion = GetCurrentRegion();
- if (_oldRegion == Region.Unknown)
- _oldRegion = currentRegion;
- if (_oldRegion == Region.Unknown)
- _oldRegion = Region.Center;
- if (currentRegion != Region.Unknown && _targetRegion == currentRegion)
- {
- Region tmp = _targetRegion;
- do
- {
- _targetRegion = GetRandomRegion();
- } while (_targetRegion == _oldRegion);
- _oldRegion = tmp;
- }
- if (_targetRegion == Region.Unknown)
- {
- do
- {
- _targetRegion = GetRandomRegion();
- } while (_targetRegion == _oldRegion);
- }
- }
- private bool TryMove()
- {
- if (_self.Type == TrooperType.Commander)
- {
- if (!Enemies.Any())
- ++_stepsWithoutEnemies;
- else
- _stepsWithoutEnemies = 0;
- }
- if (CanMove)
- {
- UpdateRegion();
- IEnumerable<Point> emptyPoints = FindEmptyPointsForRegion(_targetRegion);
- foreach (Point pt in emptyPoints)
- {
- Point[] path = FindPathTo(pt, false).ToArray();
- if (path.Length > 1)
- {
- int targetCellDangerous = CellDangerous(new Point(path[1].X, path[1].Y), _self.Stance);
- if (targetCellDangerous > CellDangerous(new Point(_self.X, _self.Y), _self.Stance) ||
- targetCellDangerous >= _self.Hitpoints)
- {
- return false;
- }
- _move.Direction = PointsToDirection(_self.X, _self.Y, path[1].X, path[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- }
- return false;
- }
- private bool TryLeaderMove()
- {
- if (Leader.Type == _self.Type)
- {
- if (_self.Type == TrooperType.Commander)
- {
- if (!Enemies.Any())
- ++_stepsWithoutEnemies;
- else
- _stepsWithoutEnemies = 0;
- }
- if (CanMove)
- {
- if (Teammates.Any(trooper => trooper.Type != _self.Type && FindPathDistance(new Point(_self.X, _self.Y), new Point(trooper.X, trooper.Y), false, true) > MaxLeaderDistance))
- return false;
- UpdateRegion();
- IEnumerable<Point> emptyPoints = FindEmptyPointsForRegion(_targetRegion);
- foreach (Point pt in emptyPoints)
- {
- Point[] path = FindPathTo(pt, false).ToArray();
- if (path.Length > 1)
- {
- int targetCellDangerous = CellDangerous(new Point(path[1].X, path[1].Y), _self.Stance);
- if (targetCellDangerous > CellDangerous(new Point(_self.X, _self.Y), _self.Stance) ||
- targetCellDangerous >= _self.Hitpoints)
- {
- return false;
- }
- _move.Direction = PointsToDirection(_self.X, _self.Y, path[1].X, path[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- }
- }
- }
- return false;
- }
- private bool TryChangeStance()
- {
- if (_self.Type == TrooperType.FieldMedic)
- return false;
- if (_self.ActionPoints < _game.StanceChangeCost)
- return false;
- switch (_self.Stance)
- {
- case TrooperStance.Prone:
- if (!GetShootableEnemies(null).Any() && !GetShootableEnemies(TrooperStance.Kneeling).Any())
- {
- _move.Action = ActionType.RaiseStance;
- _move.X = _self.X;
- _move.Y = _self.Y;
- return true;
- }
- break;
- case TrooperStance.Kneeling:
- if (GetShootableEnemies(null).Any())
- {
- if (GetShootableEnemies(TrooperStance.Prone).Any())
- {
- _move.Action = ActionType.LowerStance;
- _move.X = _self.X;
- _move.Y = _self.Y;
- return true;
- }
- }
- else
- {
- if (!GetShootableEnemies(TrooperStance.Standing).Any())
- {
- _move.Action = ActionType.RaiseStance;
- _move.X = _self.X;
- _move.Y = _self.Y;
- return true;
- }
- }
- break;
- case TrooperStance.Standing:
- if (GetShootableEnemies(null).Any() && GetShootableEnemies(TrooperStance.Kneeling).Any())
- {
- _move.Action = ActionType.LowerStance;
- _move.X = _self.X;
- _move.Y = _self.Y;
- return true;
- }
- break;
- }
- return false;
- }
- private bool TryMedicRunAway()
- {
- if (_self.Type != TrooperType.FieldMedic)
- return false;
- if (CellDangerous(new Point(_self.X, _self.Y), TrooperStance.Prone) == 0)
- return false;
- Trooper leader = Leader;
- return WhereICanGo(_self.Hitpoints/_game.StandingMoveCost - 2)
- .Where(go => CellDangerous(new Point(go.Item1, go.Item2), TrooperStance.Standing) == 0)
- .Select(go => new Tuple<int, int, int, int>(
- go.Item1,
- go.Item2,
- go.Item3,
- FindPathDistance(new Point(go.Item1, go.Item2), new Point(leader.X, leader.Y), false, false)))
- .OrderBy(go => go.Item4)
- .Select(go => new Point(go.Item1, go.Item2))
- .Any(pt =>
- {
- Point[] pts = FindPathTo(pt, false).ToArray();
- if (pts.Length > 1)
- {
- _move.Direction = PointsToDirection(_self.X, _self.Y, pts[1].X, pts[1].Y);
- _move.Action = ActionType.Move;
- return true;
- }
- return false;
- });
- }
- private bool TryRequestEnemyDisposition()
- {
- if (_self.Type != TrooperType.Commander || _self.ActionPoints < _game.CommanderRequestEnemyDispositionCost)
- return false;
- if (_stepsWithoutEnemies > 24 && _dispositionRequested == 0)
- {
- _move.Action = ActionType.RequestEnemyDisposition;
- ++_dispositionRequested;
- return true;
- }
- if (_dispositionRequested == 1)
- {
- foreach (Player player in _world.Players)
- {
- if (player.ApproximateX >= 0 && player.ApproximateY >= 0)
- {
- int x = player.ApproximateX;
- int y = player.ApproximateY;
- if (y > _world.Height / 3 && y < _world.Height / 3 * 2 &&
- x > _world.Width / 3 && x < _world.Width / 3 * 2)
- {
- _targetRegion = Region.Center;
- }
- else if (y < _world.Height / 2)
- {
- _targetRegion = x < _world.Width / 2 ? Region.NW : Region.NE;
- }
- else
- {
- _targetRegion = x < _world.Width / 2 ? Region.SW : Region.SE;
- }
- return true;
- }
- }
- ++_dispositionRequested;
- return false;
- }
- return false;
- }
- private void FillDangerField()
- {
- _dangerField = new int[_world.Width, _world.Height, 3];
- for (int k = 0; k < 3; ++k)
- {
- var stance = (TrooperStance)k;
- for (int j = 0; j < _world.Height; ++j)
- for (int i = 0; i < _world.Width; ++i)
- _dangerField[i, j, k] = CellDangerous(new Point(i, j), stance);
- }
- }
- public void Move(Trooper self, World world, Game game, Move move)
- {
- _self = self;
- _world = world;
- _game = game;
- _move = move;
- FillDangerField();
- var strategies = new List<Func<bool>>
- {
- TryEatFieldRation,
- TryKillWithGranade,
- TryKillEnemy,
- TryMoveToKillEnemy,
- TryMoveToKillWithGranade,
- TryMovingToMedicIfLowLife,
- TryUseMedikitOnHimself,
- TryUseMedikitOnOther,
- TryHealTeammate,
- TryHealHimself,
- TryMedicRunAway,
- TryThrowGranade,
- TryMoveToThrowGranade,
- TryChangeStance,
- TryShootToEnemy,
- TryGetBonusIfItNear,
- //TryMovingToLeader,
- TryMovingToEnemy,
- TryRequestEnemyDisposition,
- //TryLeaderMove,
- TryMove
- };
- if (strategies.Any(strategy => strategy()))
- return;
- move.Action = ActionType.EndTurn;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement