private int ShouldLaunchShips(ReadOnlyMap map, ReadOnlyPlanetData source, ReadOnlyPlanetData destination) { if (!IsVisible(map, source, destination)) { return(0); } return(source.OwnerId == destination.OwnerId ? ShouldLaunchReinforcementShips(map, source, destination) : ShouldLaunchAttackShips(map, source, destination)); }
public List <FleetData> ChooseFleetsToLaunch(Guid userId, ReadOnlyMap map) { if (map == null) { throw new ArgumentNullException(nameof(map)); } if (!map.Any()) { return(new List <FleetData>()); } var planetComparer = new PropertyComparer <ReadOnlyPlanetData, string>(x => x.Name); var myPlanets = map .Where(x => x.OwnerId == userId) .ToHashSet(planetComparer); var allPlanets = map .ToHashSet(planetComparer); if (myPlanets.Count == 0) { return(new List <FleetData>()); } var topPlanet = allPlanets.OrderByDescending(RankPlanet).First(); var myTopPlanet = myPlanets.OrderByDescending(RankPlanet).First(); var candidates = myPlanets .AsParallel() .SelectMany(source => { var otherPlanets = allPlanets .Except(new[] { source }, planetComparer); return(GetCandidates(map, source, otherPlanets, myTopPlanet, topPlanet)); }) .OrderByDescending(Rank) .ToList(); var sentShips = new Dictionary <string, int>(); var fleets = new List <FleetData>(); foreach (var candidate in candidates) { var sent = sentShips.GetOrCreateDefault(candidate.Source.Name); if (candidate.Ships + sent > candidate.Source.Ships) { continue; } fleets.Add(new FleetData { From = candidate.Source.Position, To = candidate.Destination.Position, Ships = candidate.Ships }); sentShips[candidate.Source.Name] += candidate.Ships; } return(fleets); }
private int ShouldLaunchReinforcementShips(ReadOnlyMap map, ReadOnlyPlanetData source, ReadOnlyPlanetData destination) { var stupidPower = (1 - source.Power) * (1 - _options.ClevernessFactor); var powerRatio = (source.Power + stupidPower) / destination.Power; var shouldLaunch = powerRatio < 1; if (!shouldLaunch) { return(0); } var ships = (int)Math.Floor(source.Ships * _options.RiskFactor); return(ships); }
private IEnumerable <Candidate> GetCandidates( ReadOnlyMap map, ReadOnlyPlanetData source, IEnumerable <ReadOnlyPlanetData> otherPlanets, ReadOnlyPlanetData myTopPlanet, ReadOnlyPlanetData topPlanet) { return(otherPlanets .Select(destination => new Candidate { Source = source, Destination = destination, Ships = ShouldLaunchShips(map, source, destination), MyTopPlanet = myTopPlanet, TopPlanet = topPlanet }) .Where(fleet => fleet.Ships > 0)); }
public List <FleetData> ChooseFleetsToLaunch(Guid userId, ReadOnlyMap map) { var myPlanets = map.Where(x => x.OwnerId == userId).ToHashSet(_planetComparer); var otherPlanets = map.Except(myPlanets, _planetComparer).ToList(); if (otherPlanets.Count == 0) { return(new List <FleetData>()); } var fleets = myPlanets .Select(source => new FleetData { From = source.Position, To = otherPlanets[_random.Next(0, otherPlanets.Count)].Position, Ships = source.Ships }) .ToList(); return(fleets); }
private int ShouldLaunchAttackShips(ReadOnlyMap map, ReadOnlyPlanetData source, ReadOnlyPlanetData destination) { var distance = map.CalculateDistance(source.Position, destination.Position); var enemyExpectedPower = (destination.Ships + destination.ProductionRate * distance) * destination.Power; var requiredShips = (int)Math.Ceiling(enemyExpectedPower / source.Power * _options.ClevernessFactor); var enoughShips = source.Ships >= requiredShips; if (!enoughShips) { return(0); } var difference = source.Ships - requiredShips; if (difference == 0) { return(requiredShips); } var addition = (int)Math.Floor(difference - _options.RiskFactor * difference); return(requiredShips + addition); }
private bool IsVisible(ReadOnlyMap map, ReadOnlyPlanetData source, ReadOnlyPlanetData destination) { var distance = map.CalculateDistance(source.Position, destination.Position); return(distance < map.MaxDistance * _options.VisionFactor); }