public void Add(ActionSequence sequence) { var moveActions = sequence.Where(a => a.ActionType == ActionType.Move && a.Formation != null).ToList(); if (moveActions.Count > 0) { var action = moveActions.First(); if (action.IsAnticollision) { if (_internalQueue.Any(s => s.Any(a => a.IsAnticollision && a.Formation == action.Formation && (a.Status == ActionStatus.Pending || a.Status == ActionStatus.Executing)))) { return; } } AbortOldActionsFor(action.Formation); } _internalQueue.Add(sequence); foreach (var action in sequence) { action.Status = ActionStatus.Pending; } }
public static void InsertToExecutingSequence(MyFormation formation, params Action[] action) { if (formation != null && formation.Alive && action.Length > 0) { var executingAction = formation.ExecutingSequence?.GetExecutingAction(); if (executingAction != null && executingAction.ActionType == ActionType.Move && executingAction.Interruptable) { action.First().StartCondition = () => true; formation.ExecutingSequence.AddRange(action); var continueAction = executingAction.Clone(); continueAction.StartCondition = () => action.Last().Status == ActionStatus.Finished || action.Last().Status == ActionStatus.Aborted; formation.ExecutingSequence.Add(continueAction); executingAction.Abort(); } if (executingAction == null) { var newSequence = new ActionSequence(action); Global.ActionQueue.Add(newSequence); } } }
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); }
public static void SetupProductionIfNeed(Facility facility, VehicleType neededType) { if (facility.Type == FacilityType.VehicleFactory && facility.VehicleType != neededType) { if (!Global.ActionQueue.HasActionsFor(facility)) { if (Global.MyVehicles.Values.All(v => v.Groups.Length == 0 || !v.IsInside(facility.Rect))) { var sequence = new ActionSequence(facility.SetupProduction(neededType)); Global.ActionQueue.Add(sequence); } } } }
public static void FinalSpread() { if (Global.World.TickIndex > 10000 && Global.World.TickIndex % 1000 == 0 && Global.MyVehicles.Count > 10 * Global.EnemyVehicles.Count && Global.World.GetMyPlayer().Score < Global.World.GetOpponentPlayer().Score) { Global.ActionQueue.Clear(); foreach (var formation in Global.MyFormations.Values) { var scale1 = formation.ScaleCenter(10); var scale2 = formation.ScaleCenter(0.1); var sequence = new ActionSequence(scale1, scale2); Global.ActionQueue.Add(sequence); } } }
public static bool OccupyFacilities(MyFormation formation) { if (formation.Alive && !formation.Busy && formation.AeralPercent < 0.1) { var freeFacility = Global.World.Facilities .OrderBy(f => f.Center.SqrDistance(formation.Center)) .FirstOrDefault(f => !f.IsMine && !f.SelectedAsTargetForGroup.HasValue); if (freeFacility != null) { freeFacility.SelectedAsTargetForGroup = formation.GroupIndex; var actionMove = formation.MoveCenterTo(freeFacility.Center); var sequence = new ActionSequence(actionMove); Global.ActionQueue.Add(sequence); return(true); } } return(false); }
public static void AbortAndAddToExecutingSequence(MyFormation formation, params Action[] action) { if (formation != null && formation.Alive && action.Length > 0) { var executingAction = formation.ExecutingSequence?.GetExecutingAction(); if (executingAction != null && executingAction.ActionType == ActionType.Move && executingAction.Interruptable) { action.First().StartCondition = () => true; formation.ExecutingSequence.AddRange(action); executingAction.Abort(); } if (executingAction == null) { var newSequence = new ActionSequence(action); Global.ActionQueue.Add(newSequence); } } }
private void Execute(ActionSequence sequence, Action action, Move move) { if (action == null) { return; } move.Action = action.ActionType; move.X = action.GetX(); move.Y = action.GetY(); move.Group = action.Group; move.Angle = action.Angle; move.Left = action.GetLeft(); move.Top = action.GetTop(); move.Right = action.GetRight(); move.Bottom = action.GetBottom(); move.VehicleType = action.VehicleType; move.MaxSpeed = action.MaxSpeed; move.MaxAngularSpeed = action.MaxAngularSpeed; move.Factor = action.Factor; move.FacilityId = action.FacilityId; move.VehicleId = action.VehicleId; if (action.Formation != null) { action.Formation.ExecutingAction = action; action.Formation.ExecutingSequence = sequence; if (action.ActionType == ActionType.ClearAndSelect) { Global.SelectedFormation = action.Formation; } } action.ExecutingMove = move; action.Status = ActionStatus.Executing; action.Callback?.Invoke(); Console.WriteLine($"Action:{action}"); }
public void Add(ActionSequence sequence) { var moveActions = sequence.Where(a => a.ActionType == ActionType.Move && a.Formation != null).ToList(); if (moveActions.Count > 0) { var action = moveActions.First(); if (action.IsAnticollision) { if (_internalQueue.Any(s => s.Any(a => a.IsAnticollision && a.Formation == action.Formation && (a.Status == ActionStatus.Pending || a.Status == ActionStatus.Executing)))) { return; } } foreach (var seq in _internalQueue) { foreach (var act in seq) { if (act.Formation == action.Formation && act.Interruptable && (act.Status == ActionStatus.Pending || act.Status == ActionStatus.Executing) && (act.ActionType == ActionType.Move || act.ActionType == ActionType.Scale || act.ActionType == ActionType.Rotate) ) { act.Abort(); } } } } _internalQueue.Add(sequence); foreach (var action in sequence) { action.Status = ActionStatus.Pending; } }
public static bool OccupyFacilities(MyFormation formation, bool breakCurrentAction) { if (formation.Alive && (!formation.Busy || breakCurrentAction) && formation.AeralPercent < 0.1) { var targetFacility = formation.FacilityAsTarget == null ? null : Global.World.Facilities.FirstOrDefault(f => f.Id == formation.FacilityAsTarget.Value); Facility freeFacility = null; if (targetFacility != null && !targetFacility.IsMine) { freeFacility = targetFacility; } else { var planningToOccupy = Global.MyFormations.Values .Where(f => f.FacilityAsTarget.HasValue) .Select(f => f.FacilityAsTarget.Value).ToList(); freeFacility = Global.NotMyFacilities .Where(f => !f.IsMine && !planningToOccupy.Contains(f.Id)) .OrderBy(f => f.Center.SqrDistance(formation.Center)).FirstOrDefault(); } if (freeFacility != null) { formation.FacilityAsTarget = freeFacility.Id; var actionMove = formation.MoveCenterTo(freeFacility.Center); var sequence = new ActionSequence(actionMove); Global.ActionQueue.Add(sequence); return(true); } } return(false); }
public void Add(ActionSequence sequence) { AddRange(sequence); }
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 void NuclearStrike() { if (Global.Me.RemainingNuclearStrikeCooldownTicks == 0 && Global.Me.NextNuclearStrikeTickIndex == -1 && Global.World.TickIndex % 30 == 25 && !Global.ActionQueue.HasActionsFor(ActionType.TacticalNuclearStrike)) { VehicleWrapper possibleTarget = null; double bestDeltaDamage = Math.Min(30 * 100, Global.EnemyVehicles.Values.Sum(i => i.Durability) / 5); var sqrNuclearRadius = Global.Game.TacticalNuclearStrikeRadius * Global.Game.TacticalNuclearStrikeRadius; const double visionRangeThreshold = 0.7; foreach (var enemy in Global.EnemyVehicles.Values) { var visors = Global.MyVehicles.Values .Where(i => i.SqrDistance(enemy) < visionRangeThreshold * i.VisionRange * i.VisionRange) .ToList(); if (visors.Count == 0) { continue; } var allDamaged = Global.AllVehicles.Values .Where(i => i.SqrDistance(enemy) < sqrNuclearRadius) .ToList(); var enemyDamaged = allDamaged.Where(i => i.PlayerId != Global.Me.Id).ToList(); var myDamaged = allDamaged.Where(i => i.PlayerId == Global.Me.Id).ToList(); if (enemyDamaged.Count <= Math.Min(30, Global.EnemyVehicles.Count / 2 - 10)) { continue; } var myDamage = myDamaged .Sum(i => Math.Min(i.Durability, Global.Game.MaxTacticalNuclearStrikeDamage * (1 - Math.Sqrt(i.SqrDistance(enemy) / sqrNuclearRadius)))); var enemyDamage = enemyDamaged .Sum(i => Math.Min(i.Durability, Global.Game.MaxTacticalNuclearStrikeDamage * (1 - Math.Sqrt(i.SqrDistance(enemy) / sqrNuclearRadius)))); if (enemyDamage - myDamage > bestDeltaDamage) { bestDeltaDamage = enemyDamage - myDamage; possibleTarget = enemy; } } if (possibleTarget == null) { return; } var visor = Global.MyVehicles.Values .Where(i => i.SqrDistance(possibleTarget) < visionRangeThreshold * i.VisionRange * i.VisionRange) .OrderBy(i => i.SqrDistance(possibleTarget)).Last(); var action = visor.TacticalNuclearStrike(possibleTarget); action.Interruptable = false; var newSequence = new ActionSequence(action); Global.ActionQueue.Add(newSequence); } }
public static bool Attack(MyFormation formation) { if (AirAttack(formation)) { return(true); } var targetFacility = formation.FacilityAsTarget == null ? null : Global.World.Facilities.FirstOrDefault(f => f.Id == formation.FacilityAsTarget.Value); if (formation.FacilityAsTarget == null) { OccupyFacilities(formation, true); targetFacility = formation.FacilityAsTarget == null ? null : Global.World.Facilities.FirstOrDefault(f => f.Id == formation.FacilityAsTarget.Value); } if (targetFacility != null) { if (targetFacility.IsMine) { targetFacility = null; formation.FacilityAsTarget = null; } } double maxAttackDistance = (targetFacility == null) ? Global.World.Width / 2 : Math.Min(100, formation.Center.Distance(targetFacility.Center) / 2); var myDurability = Global.MyVehicles.Values.Sum(v => v.Durability); var enemyDurability = Global.EnemyVehicles.Values.Sum(v => v.Durability); var betterCoeff = Math.Max(1, myDurability / (enemyDurability + 1.0)); var oneShotDanger = new Dictionary <EnemyFormation, double>(); foreach (var enemy in Global.EnemyFormations) { var dangerForEnemy = formation.DangerFor(enemy); var dangerForMe = enemy.DangerFor(formation); if (enemy.Center.Distance(formation.Center) < maxAttackDistance) { oneShotDanger.Add(enemy, (betterCoeff) * dangerForEnemy - dangerForMe); } } EnemyFormation target = null; if (oneShotDanger.Count > 0) { var targetPair = oneShotDanger .OrderByDescending(kv => kv.Value) .FirstOrDefault(); if (targetPair.Value > 0) { target = targetPair.Key; } } if (target != null) { MakeAttackOrder(formation, target, false); return(true); } var runAwayDanger = new Dictionary <EnemyFormation, double>(); foreach (var enemy in Global.EnemyFormations) { var dangerForEnemy = formation.DangerFor(enemy); var dangerForMe = enemy.DangerFor(formation); if (enemy.Center.Distance(formation.Center) < 150) { runAwayDanger.Add(enemy, (dangerForEnemy - dangerForMe) / (formation.Count + 1.0)); } } if (runAwayDanger.Count > 0) { var targetPair = runAwayDanger .OrderBy(kv => kv.Value) .FirstOrDefault(); if (targetPair.Value < -10) { var runAwayFromThis = targetPair.Key; var direction = (formation.MassCenter - runAwayFromThis.MassCenter).Normalized(); formation.FacilityAsTarget = null; Global.ActionQueue.AbortOldActionsFor(formation); var actionMove = formation.ShiftTo(direction * 100); actionMove.Priority = ActionPriority.High; actionMove.StartCondition = () => true; actionMove.Interruptable = false; var sequence = new ActionSequence(actionMove); Global.ActionQueue.Add(sequence); } } if (targetFacility != null) { var actionMove = formation.MoveCenterTo(targetFacility.Center); var sequence = new ActionSequence(actionMove); Global.ActionQueue.Add(sequence); } return(false); }
public static void SetupProductionIfNeed(Facility facility) { if (facility.Type != FacilityType.VehicleFactory) { return; } var myFightersCount = Global.MyFighters.Vehicles.Count; var myHelisCount = Global.MyHelicopters.Vehicles.Count; var enemyFightersCount = Global.EnemyFighters.Count(); var enemyHeliCount = Global.EnemyHelicopters.Count(); VehicleType neededType; bool isGroundProducing = (facility.VehicleType == null || facility.VehicleType == VehicleType.Tank || facility.VehicleType == VehicleType.Ifv || facility.VehicleType == VehicleType.Arrv); // if (myFightersCount < 0.8 * enemyFightersCount) // { // neededType = VehicleType.Fighter; // if (isGroundProducing) // { // CreateProducedFormation(); // } // } // else if (myHelisCount < 0.8 * enemyHeliCount && enemyFightersCount < 30) { neededType = VehicleType.Helicopter; if (isGroundProducing) { CreateProducedFormation(); } } else { if (facility.VehicleType == null || facility.VehicleType == VehicleType.Fighter || facility.VehicleType == VehicleType.Helicopter) { CreateProducedFormation(); facility.InitialTickIndex = 0; } facility.InitialTickIndex++; var tick = (Global.World.TickIndex - facility.InitialTickIndex) % 1200; neededType = tick < 1200 - 6 * Math.Min(150, enemyHeliCount) ? VehicleType.Tank : VehicleType.Ifv; } if (facility.VehicleType != neededType) { if (!Global.ActionQueue.HasActionsFor(facility)) { if (Global.MyVehicles.Values.All(v => v.Groups.Length == 0 || !v.IsInside(facility.Rect))) { var sequence = new ActionSequence(facility.SetupProduction(neededType)); Global.ActionQueue.Add(sequence); } } } }