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); } }
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); }