private static string GoToNearestZone(int droneIndex) { var drone = GameOfDronesManager.Player.PlayerDrones[droneIndex]; var zones = GameOfDronesManager.Zones .Where(zone => zone.OwnerId != GameOfDronesManager.PlayerId) .Select(zone => new { zone.Center.X, zone.Center.Y, zone.OwnerId, DistanceToCurrentDrone = Trigonometry.GetDistance( new Point(zone.Center.X, zone.Center.Y), new Point(drone.Location.X, drone.Location.Y)) }); var nearestZone = zones .OrderBy(zone => zone.DistanceToCurrentDrone) .FirstOrDefault(); if (nearestZone == null) { return($"{drone.Location.X} {drone.Location.Y}"); } return($"{nearestZone.X} {nearestZone.Y}"); }
public static void Act(int droneIndex) { var opponentDrones = OpponentDrone.GetOpponentDrones(); var unoccupiedZones = GameOfDronesManager.Zones.Where(zone => zone.OwnerId == -1); var heldZones = GameOfDronesManager.Zones.Where(zone => zone.OwnerId == GameOfDronesManager.PlayerId) .Select(zone => new { zone, OpponentCount = GameOfDronesManager.Participants .Select(participant => participant.Drones .Count(drone => Trigonometry.GetDistance( new Point(drone.Location.X, drone.Location.Y), new Point(zone.Center.X, zone.Center.Y)) <= GameOfDronesManager.ZoneRadius)) .OrderByDescending(count => count) .First() }); // Find empty zones and send as many as is feasible (while keeping all currently held zones occupied). var untargetedZones = GameOfDronesManager.Zones.ToList(); foreach (var targetZone in opponentDrones.Select(drone => drone.TargetZone)) { untargetedZones.RemoveAll(zone => zone.Id == targetZone.Id); } // Assign player drones to target nearest unassigned zone. Actions.Commit(GoToNearestAvailableZone(droneIndex, untargetedZones)); }
private static string GoToNearestAvailableZone( int droneIndex, IEnumerable <Zone> availableZones) { var drone = GameOfDronesManager.Player.PlayerDrones[droneIndex]; var zonesWithDistance = availableZones .Where(zone => zone.OwnerId != GameOfDronesManager.PlayerId) .Select(zone => new { zone.Center.X, zone.Center.Y, zone.OwnerId, DistanceToCurrentDrone = Trigonometry.GetDistance( new Point(zone.Center.X, zone.Center.Y), new Point(drone.Location.X, drone.Location.Y)) }); var nearestZone = zonesWithDistance.OrderBy(zone => zone.DistanceToCurrentDrone).FirstOrDefault(); if (nearestZone == null) { return(GoToNearestZone(droneIndex)); } drone.Target = $"{nearestZone.X} {nearestZone.Y}"; return(drone.Target); }
public IEnumerable <Drone> GetOccupyingDrones() { return(GameOfDronesManager.Participants .SelectMany(participant => participant.Drones .Where(drone => Trigonometry.GetDistance( new Point(drone.Location.X, drone.Location.Y), new Point(Center.X, Center.Y)) < GameOfDronesManager.ZoneRadius))); }
public Distance GetDistanceFromFlatSurface(Lander lander) { if (_landingZone == null) { SetLandingZone(); } var side = Side.Above; if (lander.Situation.X < _landingZone.LeftX) { side = Side.Left; } if (lander.Situation.X > _landingZone.RightX) { side = Side.Right; } var horizontalDistance = 0.0; var fullDistance = 0.0; if (side == Side.Left) { horizontalDistance = _landingZone.LeftX - lander.Situation.X; fullDistance = Trigonometry.GetDistance( new Point(_landingZone.LeftX, _landingZone.LeftY), new Point(lander.Situation.X, lander.Situation.Y)); } if (side == Side.Right) { horizontalDistance = _landingZone.RightX - lander.Situation.X; fullDistance = Trigonometry.GetDistance( new Point(_landingZone.RightX, _landingZone.RightY), new Point(lander.Situation.X, lander.Situation.Y)); } if (side == Side.Above) { fullDistance = Trigonometry.GetDistance( new Point(lander.Situation.X, // We are above, so we do not need to move to the left or right. _landingZone.LeftY), // Y is the same everywhere in the landing zone. new Point(lander.Situation.X, lander.Situation.Y)); } return(new Distance { HorizontalDistance = horizontalDistance, VerticalDistance = lander.Situation.Y - _landingZone.LeftY, // Y is the same everywhere in the landing zone. FullDistance = fullDistance }); }
public Distance GetDistanceFromFlatSurfaceCenter(Lander lander) { if (_landingZone == null) { SetLandingZone(); } return(new Distance { HorizontalDistance = Math.Abs(lander.Situation.X - _centerLandingZoneX), VerticalDistance = Math.Abs(lander.Situation.Y - _landingZone.LeftY), FullDistance = Trigonometry.GetDistance( new Point(_centerLandingZoneX, _landingZone.LeftY), new Point(lander.Situation.X, lander.Situation.Y)) }); }
public static IEnumerable <OpponentDrone> GetOpponentDrones() { return(GameOfDronesManager.Participants .Where(participant => !participant.IsPlayer) .Select(participant => new { Drones = participant.Drones.Select(drone => { var targetZone = TargetZoneGuesser.Guess(drone); return new OpponentDrone(drone.Id) { TargetZone = targetZone, TargetDistance = Trigonometry.GetDistance( new Point(drone.Location.X, drone.Location.Y), new Point(targetZone.Center.X, targetZone.Center.Y)), OpponentId = participant.Id }; }) }) .SelectMany(drone => drone.Drones)); }
/// <summary>Returns the node that need to be followed in order to reach the destination. Currently only works /// on a Grid, without costs associated with the movements.</summary> // This method is actually faster than the one above, even though it should not be. Might have to looks at some // of the algorithm to improve performance. public List <GridNodeAStar> GetAStarNodesWithList(string originId, string targetId) { var origin = GetNode(originId); var target = GetNode(targetId); var openSet = new List <GridNodeAStar>(); var closedSet = new HashSet <GridNodeAStar>(); var aStarOrigin = new GridNodeAStar(origin, origin, target); openSet.Add(aStarOrigin); while (openSet.Any()) { var currentNode = openSet[0]; for (var i = 1; i < openSet.Count; i++) { if (openSet[i].FCost < currentNode.FCost || openSet[i].FCost == currentNode.FCost && openSet[i].HCost < currentNode.HCost) { currentNode = openSet[i]; } } openSet.Remove(currentNode); closedSet.Add(currentNode); if (currentNode.Id == target.Id) { // Found the target node. Retracing steps. var path = new List <GridNodeAStar>(); var pathPosition = currentNode; while (pathPosition.Id != origin.Id) { path.Add(pathPosition); pathPosition = pathPosition.Parent; } path.Reverse(); return(path); } foreach (var neighbour in GetNeighbours(currentNode).Select(node => new GridNodeAStar(node, origin, target))) { if (closedSet.FirstOrDefault(node => node.Id == neighbour.Id) != null) { continue; } var newMovementCostToNeighbour = currentNode.GCost + Trigonometry.GetGridDistance( new Point(currentNode.X, currentNode.Y), new Point(neighbour.X, neighbour.Y)); var neighbourInOpenSet = openSet.FirstOrDefault(node => node.Id == neighbour.Id); if (neighbourInOpenSet == null) { // Neighbour has not been analyzed yet, so we are generating the costs and adding to open set. neighbour.GCost = newMovementCostToNeighbour; neighbour.HCost = Trigonometry.GetGridDistance( new Point(neighbour.X, neighbour.Y), new Point(target.X, target.Y)); neighbour.Parent = currentNode; openSet.Add(neighbour); } if (neighbourInOpenSet != null && newMovementCostToNeighbour > neighbourInOpenSet.GCost) { // Neighbour already exists in open set, but the new movement cost is cheaper, so we're updating it. neighbourInOpenSet.GCost = newMovementCostToNeighbour; neighbourInOpenSet.HCost = Trigonometry.GetDistance( new Point(neighbourInOpenSet.X, neighbourInOpenSet.Y), new Point(target.X, target.Y)); neighbourInOpenSet.Parent = currentNode; } } } return(new List <GridNodeAStar>()); }