private static void UpdateEnemyFormations() { // будем пересоздавать вражеские формации не каждый тик, а то посядем по быстродействию. if (Global.World.TickIndex % 10 == 0) { var allEnemyTiles = new HashSet <Tile>(); var formations = new List <List <Tile> >(); foreach (var tile in Global.DetailMap.Tiles) { if (tile.Enemies.Count != 0 && !allEnemyTiles.Contains(tile)) { var formationTiles = new List <Tile>(); AddToEnemyFormations(allEnemyTiles, formationTiles, tile); formations.Add(formationTiles); } } Global.EnemyFormations.Clear(); foreach (var formation in formations) { FormationFactory.CreateEnemyFormation(formation); } } foreach (var formation in Global.EnemyFormations) { formation.Update(Global.World.VehicleUpdates); } }
public static void CreateProducedFormation() { foreach (var facility in Global.MyFacilities) { if (facility.Type == FacilityType.VehicleFactory) { var createdVehicles = Global.MyVehicles.Values .Where(v => v.Groups.Length == 0 && v.IsInside(facility.Rect) && v.IsStanding) .ToList(); if (createdVehicles.Count > 50 || facility.NearGroundEnemyCount > 10 && createdVehicles.Count > 20) { var createdRect = new Rect(createdVehicles.Min(v => v.X), createdVehicles.Min(v => v.Y), createdVehicles.Max(v => v.X), createdVehicles.Max(v => v.Y)); var allVehiclesInsideCount = Global.MyVehicles.Values.Count(v => v.IsInside(createdRect)); if (createdVehicles.Count == allVehiclesInsideCount) { var result = FormationFactory.CreateMyFormation(createdRect.Left, createdRect.Top, createdRect.Right, createdRect.Bottom); result.Formation.ShiftTo(0, -50); Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray())); } } } } }
public static void CreateProducedFormation() { foreach (var facility in Global.MyFacilities) { if (facility.Type == FacilityType.VehicleFactory) { List <VehicleWrapper> createdVehicles = facility.CreatedVehicles; if (createdVehicles.Count > 40 || facility.NearGroundEnemyCount > 10 && createdVehicles.Count > 20) { Rect createdRect = facility.CreatedVehiclesRect; var allVehiclesInsideCount = Global.MyVehicles.Values.Count(v => v.IsInside(createdRect)); if (createdVehicles.Count == allVehiclesInsideCount) { var stopProduction = facility.StopProduction(); var result = FormationFactory.CreateMyFormation(createdRect.Left, createdRect.Top, createdRect.Right, createdRect.Bottom); result.ActionList.Insert(0, stopProduction); foreach (var action in result.ActionList) { action.Priority = ActionPriority.High; } Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray())); } } } } }
public static void SplitFormation(MyFormation formation, int runFromCenter = 0) { var child = FormationFactory.CreateMyFormation( () => formation.Rect.Left, () => formation.Rect.Top, () => formation.MassCenter.X, () => formation.MassCenter.Y); formation.Children.Add(child.Formation); var sequence = new ActionSequence(child.ActionList.ToArray()); if (runFromCenter > 0) { sequence.Add(child.Formation.ShiftTo(-runFromCenter, -runFromCenter)); } child = FormationFactory.CreateMyFormation( () => formation.MassCenter.X, () => formation.Rect.Top, () => formation.Rect.Right, () => formation.MassCenter.Y); sequence.AddRange(child.ActionList); formation.Children.Add(child.Formation); if (runFromCenter > 0) { sequence.Add(child.Formation.ShiftTo(runFromCenter, -runFromCenter)); } child = FormationFactory.CreateMyFormation( () => formation.Rect.Left, () => formation.MassCenter.Y, () => formation.MassCenter.X, () => formation.Rect.Bottom); sequence.AddRange(child.ActionList); formation.Children.Add(child.Formation); if (runFromCenter > 0) { sequence.Add(child.Formation.ShiftTo(-runFromCenter, runFromCenter)); } child = FormationFactory.CreateMyFormation( () => formation.MassCenter.X, () => formation.MassCenter.Y, () => formation.Rect.Right, () => formation.Rect.Bottom); sequence.AddRange(child.ActionList); formation.Children.Add(child.Formation); if (runFromCenter > 0) { sequence.Add(child.Formation.ShiftTo(runFromCenter, runFromCenter)); } Global.ActionQueue.Add(sequence); }
private static void CreateAndScale(VehicleType vehicleType) { var factor = 0.5; var result = FormationFactory.CreateMyFormation(vehicleType); var scaleAction = result.Formation.ScaleCenter(factor); scaleAction.StartCondition = () => { return(result.ActionList.Last(a => a.ActionType == ActionType.Assign).Status == ActionStatus.Finished); }; result.ActionList.Add(scaleAction); Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray())); }
public static MyFormation CreateAirFormation() { const double eps = 10D; const double deltaShift = 5.1D; const double commonCoordinate = 350D; const double nearCoordinate = 60D; const double farCoordinate = 200D; const double factor = 1.7D; const double vehicleSize = 4D; var fighters = Global.MyFighters; var helicopters = Global.MyHelicopters; Global.IgnoreCollisionGroupIndexes.Add(fighters.GroupIndex); Global.IgnoreCollisionGroupIndexes.Add(helicopters.GroupIndex); var isVertical = Math.Abs(fighters.Rect.Left - helicopters.Rect.Left) < eps; MyFormation f1; MyFormation f2; double f1MoveX; double f1MoveY; double f2MoveX; double f2MoveY; double shiftX; double shiftY; double compactX; double compactY; double angle; if (isVertical) { f1MoveX = commonCoordinate + deltaShift; f1MoveY = nearCoordinate; f2MoveX = commonCoordinate; f2MoveY = farCoordinate; shiftX = 0; shiftY = (farCoordinate - nearCoordinate) / 2; compactX = 0; compactY = 3 * vehicleSize; angle = -Math.PI / 4; } else { f1MoveX = nearCoordinate; f1MoveY = commonCoordinate + deltaShift; f2MoveX = farCoordinate; f2MoveY = commonCoordinate; shiftX = (farCoordinate - nearCoordinate) / 2; shiftY = 0; compactX = 3 * vehicleSize; compactY = 0; angle = Math.PI / 4; } if (isVertical && fighters.Rect.Top < helicopters.Rect.Top || !isVertical && fighters.Rect.Left < helicopters.Rect.Left) { f1 = fighters; f2 = helicopters; } else { f1 = helicopters; f2 = fighters; } // двигаем первую формацию налево или вниз, а потом - масштабируем ее var sMove1 = new ActionSequence( f1.MoveLeftTopTo(f1MoveX, f1MoveY), f1.ScaleLeftTop(factor) ); Global.ActionQueue.Add(sMove1); // двигаем вторую формацию налево или вниз, а потом - масштабируем ее var sMove2 = new ActionSequence( f2.MoveLeftTopTo(f2MoveX, f2MoveY), f2.ScaleLeftTop(factor) ); Global.ActionQueue.Add(sMove2); // после того, как обе формации отмасштабированы, первая формация движеться наствречу второй var aPenetrate1 = f1.ShiftTo(shiftX, shiftY); aPenetrate1.StartCondition = () => sMove1.IsFinished && sMove2.IsFinished; var sPenetrate1 = new ActionSequence(aPenetrate1); Global.ActionQueue.Add(sPenetrate1); // а вторая - навстречу первой до полного проникновения var aPenetrate2 = f2.ShiftTo(-shiftX, -shiftY); aPenetrate2.StartCondition = () => sMove1.IsFinished && sMove2.IsFinished; var sPenetrate2 = new ActionSequence(aPenetrate2); Global.ActionQueue.Add(sPenetrate2); // сплющиваем сбоку бутерброд var res = FormationFactory.CreateMyFormation( () => Math.Min(f1.Rect.Left, f2.Rect.Left), () => Math.Min(f1.Rect.Top, f2.Rect.Top), () => Math.Max(f1.Rect.Right, f2.Rect.Right) - compactX, () => Math.Max(f1.Rect.Bottom, f2.Rect.Bottom) - compactY); Global.IgnoreCollisionGroupIndexes.Add(res.GroupIndex); var sShift = new ActionSequence(res.ActionList.ToArray()); sShift.First().StartCondition = () => sPenetrate2.IsFinished && sPenetrate1.IsFinished; sShift.Add(res.Formation.ShiftTo(shiftX, shiftY)); Global.ActionQueue.Add(sShift); // компактизируем res = FormationFactory.CreateMyFormation( () => Math.Min(f1.Rect.Left, f2.Rect.Left), () => Math.Min(f1.Rect.Top, f2.Rect.Top), () => Math.Max(f1.Rect.Right, f2.Rect.Right), () => Math.Max(f1.Rect.Bottom, f2.Rect.Bottom)); var sCompact = new ActionSequence(res.ActionList.ToArray()); sCompact.First().StartCondition = () => sShift.IsFinished; sCompact.Add(res.Formation.ScaleCenter(1.2)); sCompact.Add(res.Formation.RotateCenter(angle)); sCompact.Add(res.Formation.ScaleCenter(0.5)); sCompact.Add(res.Formation.ShiftTo(10, 10)); Global.ActionQueue.Add(sCompact); return(res.Formation); }
public static bool Attack(MyFormation formation) { var enemyFightersCount = Global.EnemyFighters.Count(); if (formation == Global.MyHelicopters && enemyFightersCount > 30) { var enemyFighters = FormationFactory.CreateEnemyFormation(Global.EnemyFighters); if ((enemyFighters.Rect.RightBottom - enemyFighters.Rect.LeftTop).Length() < 300) { MyFormation foundAllyGround = null; if (Global.MyIfvs.Alive && Global.MyIfvs.Vehicles.Count > 30) { foundAllyGround = Global.MyIfvs; } else if (Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 30) { foundAllyGround = Global.MyArrvs; } if (foundAllyGround != null) { var actionMove = formation.MoveCenterTo(Global.MyIfvs.Center); AbortAndAddToExecutingSequence(formation, actionMove); return(true); } } } if (formation == Global.MyFighters) { if (enemyFightersCount > 10) { var enemy = FormationFactory.CreateEnemyFormation(Global.EnemyFighters); var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length(); if (enemyLength < 200) { MakeAttackOrder(formation, enemy, true); return(true); } } if (Global.EnemyHelicopters.Count() > 10) { var enemy = FormationFactory.CreateEnemyFormation(Global.EnemyHelicopters); var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length(); if (enemyLength < 300) { MakeAttackOrder(formation, enemy, true); return(true); } } // if (Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 30) // { // var actionMove = formation.MoveCenterTo(Global.MyArrvs.Center); // AbortAndAddToExecutingSequence(formation, actionMove); // return true; // } } var oneShotDanger = new Dictionary <EnemyFormation, double>(); foreach (var enemy in Global.EnemyFormations) { var dangerForEnemy = formation.DangerFor(enemy); var dangerForMe = enemy.DangerFor(formation); oneShotDanger.Add(enemy, dangerForEnemy - dangerForMe); } // todo: давать правильную команду // выбирать также по расстоянию EnemyFormation target = null; var targetPair = oneShotDanger.OrderByDescending(kv => kv.Value).First(); if (targetPair.Value > 0) { target = targetPair.Key; } if (target != null) { var targetFacility = Global.World.Facilities .Where(f => f.SelectedAsTargetForGroup == formation.GroupIndex).ToList(); if (targetFacility.Any()) { foreach (var facility in targetFacility) { facility.SelectedAsTargetForGroup = null; } OccupyFacilities(formation); return(true); } MakeAttackOrder(formation, target, false); return(true); } return(false); }
public static void Anticollision() { if (Global.JoinFormation1 != null && Global.JoinFormation1.Alive && Global.JoinFormation1.Count > 0 && Global.JoinFormation2 != null && Global.JoinFormation2.Alive && Global.JoinFormation2.Count > 0) { var result = FormationFactory.CreateMyFormation(Global.JoinFormation1, Global.JoinFormation2); Global.JoinFormation1 = null; Global.JoinFormation2 = null; Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray())); return; } var processedKeys = new List <int>(); foreach (var key1 in Global.MyFormations.Keys) { var f1 = Global.MyFormations[key1]; if (f1.Alive && !Global.IgnoreCollisionGroupIndexes.Contains(key1)) { foreach (var facility in Global.MyFacilities.Where(f => f.Type == FacilityType.VehicleFactory && f.VehicleType.HasValue)) { var facRect = facility.CreatedVehiclesRect; if (f1.IsAllAeral && facility.CreatedVehicles.All(v => v.IsAerial) || f1.IsAllGround && facility.CreatedVehicles.All(v => !v.IsAerial)) { var distBetweenCenters = f1.Rect.Center.SqrDistance(facRect.Center); if (distBetweenCenters < (f1.Rect.SqrDiameter + facRect.SqrDiameter) / 2) { if (!processedKeys.Contains(key1)) { processedKeys.Add(key1); var delta = f1.Center - facRect.Center; var normalizedSpeed = f1.AvgSpeed.Normalized(); var rotated = new Point(normalizedSpeed.Y, -normalizedSpeed.X); delta = delta.Normalized(); CompactAndContinue(f1, 50 * (delta + rotated / 2)); } } } } foreach (var key2 in Global.MyFormations.Keys.Where(k => k != key1)) { var f2 = Global.MyFormations[key2]; if (f2.Alive && !Global.IgnoreCollisionGroupIndexes.Contains(key2) && (f1.IsMixed || f2.IsMixed || f1.IsAllAeral == f2.IsAllAeral)) { var distBetweenCenters = f1.Rect.Center.SqrDistance(f2.Rect.Center); if (distBetweenCenters < (f1.Rect.SqrDiameter + f2.Rect.SqrDiameter) / 2) { var delta = f1.Center - f2.Center; if (Global.MyFormations.Count > 15 && f1.Count < 50 && f2.Count < 50 && !processedKeys.Contains(key1) && !processedKeys.Contains(key2)) { processedKeys.Add(key1); processedKeys.Add(key2); Global.JoinFormation1 = f1; Global.JoinFormation2 = f2; return; } else { if (!processedKeys.Contains(key1)) { processedKeys.Add(key1); var delta1 = 20 * (delta.Normalized() + f1.AvgSpeed.Normalized() / 2); CompactAndContinue(f1, delta1); } if (!processedKeys.Contains(key2)) { processedKeys.Add(key2); var delta2 = 20 * (delta.Normalized() + f2.AvgSpeed.Normalized() / 2); CompactAndContinue(f2, -1 * delta2); } } } } } } } }
private static bool AirAttack(MyFormation formation) { if (formation != Global.MyHelicopters && formation != Global.MyFighters) { return(false); } if (Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 10) { var durabilityPercent = formation.Durability / (formation.MaxDurability + 1); if (durabilityPercent < 0.7 || (durabilityPercent < 0.9 && formation.Center.Distance(Global.MyArrvs.Center) < 100)) { if (MoveToAlly(formation, Global.MyArrvs)) { return(true); } } } var enemyFightersCount = Global.EnemyFighters.Count(); if (formation == Global.MyHelicopters) { if (enemyFightersCount > 30) { var enemyFighters = FormationFactory.CreateEnemyFormation(Global.EnemyFighters); var isMyArrvsCanProtect = Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 30; var distanceToProtection = isMyArrvsCanProtect ? Global.MyArrvs.Rect.Center.Distance(formation.Center) : 0; if ((enemyFighters.Rect.RightBottom - enemyFighters.Rect.LeftTop).Length() < 300 && enemyFighters.Rect.Center.Distance(formation.Center) < distanceToProtection) { MyFormation foundAllyGround = null; if (Global.MyIfvs.Alive && Global.MyIfvs.Vehicles.Count > 30) { foundAllyGround = Global.MyIfvs; } else if (isMyArrvsCanProtect) { foundAllyGround = Global.MyArrvs; } if (foundAllyGround != null) { var actionMove = formation.MoveCenterTo(foundAllyGround.Center); AbortAndAddToExecutingSequence(formation, actionMove); return(true); } } } if (Global.EnemyVehicles.Count == 0) { var actionMove = formation.MoveCenterTo(Global.World.Width / 3 - 100, Global.World.Height / 3); AbortAndAddToExecutingSequence(formation, actionMove); return(true); } } if (formation == Global.MyFighters) { if (enemyFightersCount > 10) { var rect = new Rect(Global.EnemyFighters.Min(f => f.X), Global.EnemyFighters.Min(f => f.Y), Global.EnemyFighters.Max(f => f.X), Global.EnemyFighters.Max(f => f.Y)); var allEnemiesNearFighters = Global.EnemyVehicles.Values.Where(v => v.IsInside(rect)); var enemy = FormationFactory.CreateEnemyFormation(allEnemiesNearFighters); var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length(); if (enemyLength < 200) { if (AttackOrRunAway(formation, enemy)) { return(true); } } } if (Global.EnemyHelicopters.Count() > 10) { var rect = new Rect(Global.EnemyHelicopters.Min(f => f.X), Global.EnemyHelicopters.Min(f => f.Y), Global.EnemyHelicopters.Max(f => f.X), Global.EnemyHelicopters.Max(f => f.Y)); var allEnemiesNearHeli = Global.EnemyVehicles.Values.Where(v => v.IsInside(rect)); var enemy = FormationFactory.CreateEnemyFormation(allEnemiesNearHeli); var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length(); if (enemyLength < 300) { if (AttackOrRunAway(formation, enemy)) { return(true); } } } if (Global.EnemyVehicles.Count == 0) { var actionMove = formation.MoveCenterTo(Global.World.Width / 2 + 100, Global.World.Height / 2); AbortAndAddToExecutingSequence(formation, actionMove); return(true); } } return(false); }