static double GetSumMaxAlmostAttacks(Sandbox env, IEnumerable <AVehicle> myVehicles) { Logger.CumulativeOperationStart("Danger0"); var result = myVehicles.Sum(m => { var additionalRadius = m.ActualSpeed; const int radiusFactor = 5; return(env.GetOpponentNeighbours(m.X, m.Y, G.MaxAttackRange + additionalRadius * radiusFactor).DefaultIfEmpty(null) .Max(opp => { if (opp == null) { return 0; } var dmg = opp.GetAttackDamage(m, additionalRadius * radiusFactor); if (dmg == 0) { return -(m.GetAttackDamage(opp, additionalRadius) + m.GetAttackDamage(opp, additionalRadius * radiusFactor) / 2.0); } return (opp.GetAttackDamage(m, additionalRadius) + opp.GetAttackDamage(m, additionalRadius * 2) / 2.0 + opp.GetAttackDamage(m, additionalRadius * 3) / 4.0 + opp.GetAttackDamage(m, additionalRadius * 4) / 8.0 + dmg / 16.0 ) * (G.AttackDamage[(int)m.Type, (int)opp.Type] > 0 ? Geom.Sqr(1.0 * opp.Durability / G.MaxDurability) : 1) * (m.Type == opp.Type ? 0.6 : 1) * (G.IsAerialButerDetected && opp.Type == VehicleType.Fighter ? 3 : 1); })); }); Logger.CumulativeOperationEnd("Danger0"); return(result); }
private Tuple <double, AMove> _nuclearFindMove(Sandbox env, double selTotalDamage, bool checkOnly) { AMove selMove = null; for (var s = 0; s < GroupsManager.MyGroups.Count + MyUngroupedClusters.Count; s++) { var vehicles = s < GroupsManager.MyGroups.Count ? env.GetVehicles(true, GroupsManager.MyGroups[s]) : MyUngroupedClusters[s - GroupsManager.MyGroups.Count]; var myAvg = Utility.Average(vehicles); var vrg = G.VisionRange[(int)VehicleType.Fighter] + G.MaxTacticalNuclearStrikeDamage; var oppGroups = OppClusters .Where(cl => cl.Avg.GetDistanceTo(myAvg) < vrg && cl.Any(x => env.VehicleById.ContainsKey(x.Id)))// пропускать полностью фантомные группы .OrderBy(cl => cl.Avg.GetDistanceTo(myAvg)) .Take(3) .ToArray(); foreach (var veh in vehicles) { if (!veh.IsSelected && MoveObserver.AvailableActions < 3) { continue; } if (veh.IsSelected && MoveObserver.AvailableActions < 2) { continue; } var vr = veh.ActualVisionRange * 0.9; foreach ( var oppGroup in new[] { env.GetOpponentNeighbours(veh.X, veh.Y, vr + G.TacticalNuclearStrikeRadius) }.Concat(oppGroups)) { ANuclear nuclear; var totalDamage = _nuclearGetDamage(veh, env, selTotalDamage, oppGroup, out nuclear); if (totalDamage <= selTotalDamage) { continue; } var vehNextMove = new AVehicle(veh); for (var t = 0; t < 3; t++) { vehNextMove.Move(); } if (vehNextMove.GetDistanceTo2(nuclear) + Const.Eps >= Geom.Sqr(vehNextMove.ActualVisionRange)) { continue; } const int n = 10; if (vehicles.Count > n) { var myDist2 = veh.GetDistanceTo2(nuclear); var myNearestCount = vehicles.Count(x => x.GetDistanceTo2(nuclear) <= myDist2); if (myNearestCount < n) { continue; } } selTotalDamage = totalDamage; selMove = new AMove { Action = ActionType.TacticalNuclearStrike, VehicleId = veh.Id, Point = nuclear, }; if (checkOnly) { return(new Tuple <double, AMove>(selTotalDamage, selMove)); } } } } if (selMove == null) { return(null); } return(new Tuple <double, AMove>(selTotalDamage, selMove)); }