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); } } }
private static void CompactAndContinue(MyFormation form, Point delta) { const double densistyLimit = 0.01; var move = form.ShiftTo(delta); // move.Interruptable = false; move.IsAnticollision = true; if (form.Density < densistyLimit && form.Alive && form.Count > 0) { var scale1 = form.ScalePoint(form.MassCenter, 0.1); // scale1.Interruptable = false; scale1.IsAnticollision = true; scale1.AbortAtWorldTick = Global.World.TickIndex + (int)(Math.Sqrt(form.Rect.SqrDiameter) / (4 * form.MaxSpeed)); var rotate = form.RotateCenter(Math.PI / 2); // rotate.Interruptable = false; rotate.StartCondition = () => Global.World.TickIndex >= scale1.AbortAtWorldTick; rotate.AbortAtWorldTick = scale1.AbortAtWorldTick + 10; move.StartCondition = () => Global.World.TickIndex >= rotate.AbortAtWorldTick; InsertToExecutingSequence(form, scale1, rotate, move); } else { InsertToExecutingSequence(form, move); } }
private static bool AttackOrRunAway(MyFormation formation, EnemyFormation enemy) { foreach (var enemyFormation in Global.EnemyFormations) { if (enemyFormation.Rect.IsInside(enemy.Center)) { var dangerForEnemy = formation.DangerFor(enemy); var dangerForMe = enemy.DangerFor(formation); if (dangerForMe < dangerForEnemy * 1.5) { MakeAttackOrder(formation, enemy, true); return(true); } if (MoveToAlly(formation, Global.MyArrvs)) { return(true); } if (MoveToAlly(formation, Global.MyIfvs)) { return(true); } if (MoveToAlly(formation, Global.MyTanks)) { return(true); } } } return(false); }
public static FormationResult CreateMyFormation(VehicleType type) { var formation = new MyFormation { GroupIndex = 1 + (int)type, Alive = false, Type = type }; var left = Global.MyVehicles.Values.Where(v => v.Type == type).Min(v => v.X); var top = Global.MyVehicles.Values.Where(v => v.Type == type).Min(v => v.Y); var right = Global.MyVehicles.Values.Where(v => v.Type == type).Max(v => v.X); var bottom = Global.MyVehicles.Values.Where(v => v.Type == type).Max(v => v.Y); var list = SelectAndAssignVehicles(formation, () => left, () => top, () => right, () => bottom, formation.GroupIndex); Global.MyFormations.Add(formation.GroupIndex, formation); return(new FormationResult { Formation = formation, GroupIndex = formation.GroupIndex, ActionList = list }); }
private static bool MoveToAlly(MyFormation formation, MyFormation allyFormation) { if (allyFormation.Alive && allyFormation.Vehicles.Count > 10) { var actionMove = formation.MoveCenterTo(allyFormation.Center); AbortAndAddToExecutingSequence(formation, actionMove); return(true); } return(false); }
public Action(MyFormation formation, int minimumDuration = DefaultMinimalDuration) { Formation = formation; MinimumDuration = minimumDuration; if (Formation != null) { FinishCondition = () => !Formation.Busy; StartCondition = () => !Formation.Busy && Formation.Vehicles.Count > 0; } }
public static Action ScaleLeftTop(this MyFormation formation, double factor) { var action = new Action(formation) { ActionType = ActionType.Scale, Factor = factor, GetX = () => formation.Rect.Left, GetY = () => formation.Rect.Top }; return(action); }
public static Action ScalePoint(this MyFormation formation, Point point, double factor) { var action = new Action(formation) { ActionType = ActionType.Scale, Factor = factor, GetX = () => point.X, GetY = () => point.Y }; return(action); }
public static Action ScaleCenter(this MyFormation formation, double factor) { var action = new Action(formation) { ActionType = ActionType.Scale, Factor = factor, GetX = () => formation.MassCenter.X, GetY = () => formation.MassCenter.Y }; return(action); }
public static Action MoveCenterTo(this MyFormation formation, double x, double y, double maxSpeed = 10) { var action = new Action(formation) { ActionType = ActionType.Move, GetX = () => x - formation.MassCenter.X, GetY = () => y - formation.MassCenter.Y, MaxSpeed = maxSpeed }; return(action); }
public static Action RotateCenter(this MyFormation formation, double angle) { var action = new Action(formation) { ActionType = ActionType.Rotate, Angle = angle, GetX = () => formation.MassCenter.X, GetY = () => formation.MassCenter.Y }; return(action); }
public static Action ShiftTo(this MyFormation formation, double x, double y, double maxSpeed = 10) { var action = new Action(formation) { ActionType = ActionType.Move, GetX = () => x, GetY = () => y, MaxSpeed = maxSpeed }; return(action); }
public static Action MoveLeftTopTo(this MyFormation formation, double x, double y, double maxSpeed = 10) { var action = new Action(formation) { GetX = () => x - formation.Rect.Left, GetY = () => y - formation.Rect.Top, ActionType = ActionType.Move, MaxSpeed = maxSpeed }; return(action); }
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 List <Action> SelectAndAssignVehicles(MyFormation formation, Func <double> left, Func <double> top, Func <double> right, Func <double> bottom, int groupIndex) { var selectAction = new Action { ActionType = ActionType.ClearAndSelect, GetLeft = left, GetTop = top, GetRight = right, GetBottom = bottom, }; selectAction.Callback = () => { var rect = new Rect(left(), top(), right(), bottom()); foreach (var keyVal in Global.MyVehicles) { if (keyVal.Value.IsInside(rect)) { formation.Vehicles.Add(keyVal.Key, keyVal.Value); } } formation.Update(); selectAction.Status = ActionStatus.Finished; }; var assignAction = new Action { ActionType = ActionType.Assign, Group = groupIndex, // IsUrgent = true }; assignAction.Callback = () => { formation.Alive = true; assignAction.Status = ActionStatus.Finished; }; return(new List <Action> { selectAction, assignAction }); }
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); } } }
public static FormationResult CreateMyFormation(Func <double> left, Func <double> top, Func <double> right, Func <double> bottom) { var formation = new MyFormation { GroupIndex = GetMyFreeFormationIndex(), Alive = false }; var list = SelectAndAssignVehicles(formation, left, top, right, bottom, formation.GroupIndex); Global.MyFormations.Add(formation.GroupIndex, formation); return(new FormationResult { Formation = formation, GroupIndex = formation.GroupIndex, ActionList = list }); }
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 static Action ShiftTo(this MyFormation formation, Point point, double maxSpeed = 10) { return(ShiftTo(formation, point.X, point.Y, maxSpeed)); }
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); }
public static FormationResult CreateMyFormation(MyFormation f1, MyFormation f2) { var center = (f1.Rect.Center + f2.Rect.Center) / 2; var formation = new MyFormation { GroupIndex = GetMyFreeFormationIndex(), Alive = false, Type = f1.Type }; Global.ActionQueue.AbortOldActionsFor(f1); Global.ActionQueue.AbortOldActionsFor(f2); var select1 = f1.GetSelectionAction(); select1.Priority = ActionPriority.High; var select2 = f2.GetSelectionAction(); select2.ActionType = ActionType.AddToSelection; select2.Priority = ActionPriority.High; foreach (var vehicle in f1.Vehicles) { formation.Vehicles.Add(vehicle.Key, vehicle.Value); } foreach (var vehicle in f2.Vehicles) { formation.Vehicles.Add(vehicle.Key, vehicle.Value); } var assign = new Action { ActionType = ActionType.Assign, Group = formation.GroupIndex, Priority = ActionPriority.High }; assign.Callback = () => { formation.Update(); formation.Alive = true; assign.Status = ActionStatus.Finished; }; Global.MyFormations.Remove(f1.GroupIndex); Global.MyFormations.Remove(f2.GroupIndex); Global.MyFormations.Add(formation.GroupIndex, formation); var scale1 = formation.ScalePoint(center, 0.1); scale1.Priority = ActionPriority.High; var scale2 = formation.ScalePoint(center, 1.1); scale2.Priority = ActionPriority.High; return(new FormationResult { Formation = formation, GroupIndex = formation.GroupIndex, ActionList = new List <Action> { select1, select2, assign, scale1, scale2 } }); }
public bool HasActionsFor(MyFormation formation) { return(_internalQueue.Any(sequence => sequence.Any(a => a.Formation == formation))); }
public static Action MoveLeftTopTo(this MyFormation formation, Point point, double maxSpeed = 10) { return(MoveLeftTopTo(formation, point.X, point.Y)); }
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 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 bool MakeAttackOrder(MyFormation me, EnemyFormation enemy, bool breakCurrentAction) { if (!(me.Alive && (!me.Busy || breakCurrentAction))) { return(false); } var pointToMove = enemy == null ? Point.EndOfWorld / 2 : enemy.MassCenter; var myMassCenter = me.MassCenter; var distance = pointToMove.Distance(myMassCenter); if (enemy != null) { var enemySpeedScalar = enemy.AvgSpeed.Length(); var mySpeedScalar = me.MaxSpeed; var myDirection = (pointToMove - myMassCenter).Normalized(); var enemyDirection = enemy.AvgSpeed.Normalized(); var resultDirection = (myDirection + enemySpeedScalar / mySpeedScalar * enemyDirection).Normalized(); pointToMove = myMassCenter + distance * resultDirection; } if (distance > 100) { pointToMove = (me.Center + pointToMove) / 2; } if (me.ExecutingAction != null && me.ExecutingAction.ActionType == ActionType.Move) { var oldVector = new Point(me.ExecutingAction.GetX(), me.ExecutingAction.GetY()); var newVector = pointToMove - me.Center; var scalar = oldVector.Normalized() * newVector.Normalized(); if (scalar > 0.95) // около 18 градусов { return(false); } } var actionMove = me.MoveCenterTo(pointToMove); if (me.Density < 0.01 && distance > 200) { var actionScale = me.ScaleCenter(0.1); AbortAndAddToExecutingSequence(me, actionScale, actionMove); } else { AbortAndAddToExecutingSequence(me, actionMove); } foreach (var facility in Global.World.Facilities) { if (facility.SelectedAsTargetForGroup == me.GroupIndex) { facility.SelectedAsTargetForGroup = null; } } return(true); }