void AlternativeMove(Points pts) { var car = new ACar(self); var backBruteRes = _doAndSelectBrute(BackBrutes, pts); if (backBruteRes.Item1 != -1) { BackBrutes[backBruteRes.Item1].SelectThis(); var mv = backBruteRes.Item2[backBruteRes.Item1]; if (mv.Count > 0) { mv[0].Apply(move, new ACar(self)); ComputedPath[self.Id] = GetCarPath(self, mv); #if DEBUG Visualizer.DrawWays(self, backBruteRes.Item2, backBruteRes.Item1); #endif return; } } // change points pts = GetAlternativeWaySegments(self); var turnCenter = pts[1]; var tmp = new ACar(self); var aa = tmp + tmp.Speed; if (Math.Abs(tmp.GetAngleTo(aa)) > Math.PI / 2) { move.EnginePower = 1; move.WheelTurn *= -1; return; } move.EnginePower = 1.0; if (car.GetDistanceTo(turnCenter) < 1.6 * Const.TileSize) { move.EnginePower = 0.8; } if (car.GetDistanceTo(turnCenter) < 1.0 * Const.TileSize) { if (GetSpeed(self) > 11) { move.IsBrake = true; } } move.WheelTurn = car.GetAngleTo(turnCenter); if (BAD_TESTING_STRATEGY) { if (turnCenter.GetDistanceTo(self) >= 7 * Const.TileSize && Math.Abs(car.GetAngleTo(turnCenter)) < Math.PI / 6) { move.IsUseNitro = true; } } }
private void _carMoveFunc(ACar model, int from, int to, int step, AMove m, PassedInfo passed, CarCallback callback) { model = model.Clone(); passed = passed.Clone(); m.Times = 0; for (var t = 0; t < from; t++) { if (!_modelMove(model, m, passed)) { return; } m.Times++; } for (var t = from; t <= to; t += step) { _movesStack.Add(m); callback(model, passed); _movesStack.Pop(); for (var r = 0; r < step; r++) { if (!_modelMove(model, m, passed)) { return; } m.Times++; } } }
/* * Проверка что кто-то стоит впереди * p2 p5 p3 p4 p1 * | | | | | * o-----------------o * | | * | | */ public bool IsSomeoneAhead(ACar car, int direction) { var carRect = car.GetRect(0); Point p1, p2; if (direction > 0) { p1 = carRect[0] + Point.ByAngle(car.Angle) * 20; p2 = carRect[3] + Point.ByAngle(car.Angle) * 20; } else { p1 = carRect[1] - Point.ByAngle(car.Angle) * 20; p2 = carRect[2] - Point.ByAngle(car.Angle) * 20; } var p3 = (p1 + p2) / 2; var p4 = (p1 + p3) / 2; var p5 = (p2 + p3) / 2; return(world.Cars.Select(x => new ACar(x).GetRect(0)).Any( rect => Geom.ContainPoint(rect, p1) || Geom.ContainPoint(rect, p2) || Geom.ContainPoint(rect, p3) || Geom.ContainPoint(rect, p4) || Geom.ContainPoint(rect, p5) )); }
public bool IntersectWith(ACar car, double safeMargin) { if (GetDistanceTo2(car) > Geom.Sqr(Const.CarDiagonalHalfLength + Const.CarDiagonalHalfLength)) { return(false); } return(Geom.PolygonsIntersect(GetRect(0), car.GetRect(safeMargin))); }
public AOilSlick(ACar car) { var dist = Const.Game.OilSlickInitialRange + car.Original.Width / 2 + Const.Game.OilSlickRadius; var slick = car - Point.ByAngle(car.Angle) * dist; X = slick.X; Y = slick.Y; Radius = Const.Game.OilSlickRadius; RemainingLifetime = Const.Game.OilSlickLifetime; }
public bool Intersect(ACar car, double extendRadius) { if (Type == ProjectileType.Washer) return Geom.ContainPoint(car.GetRect(-extendRadius), this); var r = Radius + extendRadius; if (GetDistanceTo2(car) > Geom.Sqr(r + Const.CarDiagonalHalfLength)) return false; return car.GetRectEx().Any(p => GetDistanceTo(p) < r); }
public bool Intersect(ACar car, double extendRadius) { if (Type == ProjectileType.Washer) { return(Geom.ContainPoint(car.GetRect(-extendRadius), this)); } var r = Radius + extendRadius; if (GetDistanceTo2(car) > Geom.Sqr(r + Const.CarDiagonalHalfLength)) { return(false); } return(car.GetRectEx().Any(p => GetDistanceTo(p) < r)); }
bool CheckBackMove(Point turnCenter) { const int ticksToCheck = 40; for (var power = -1; power <= 1; power += 2) { if (BackModeRemainTicks == 0 && PositionsHistory.Count > ticksToCheck) { if ( PositionsHistory[PositionsHistory.Count - 1].GetDistanceTo( PositionsHistory[PositionsHistory.Count - ticksToCheck]) < 20) { var model = new ACar(self) { EnginePower = -power }; var cnt = 0; for (var i = 0; i < 80; i++) { if (ModelMove(model, new AMove { EnginePower = -power, IsBrake = false, WheelTurn = 0 }, simpleMode: false, exactlyBorders: true)) { cnt++; } } if (cnt < 25 || IsSomeoneAhead(new ACar(self), -power)) { BackModeRemainTicks = 50; BackModeTurn = self.GetAngleTo(turnCenter.X, turnCenter.Y) < 0 ? -power : power; BackModePower = power; break; } } } } if (BackModeRemainTicks > 0) { BackModeRemainTicks--; move.EnginePower = BackModePower; move.WheelTurn = BackModeTurn; return(true); } return(false); }
public static ACar[] GetCarPath(Car self, Moves stack) { if (stack == null) return null; stack = stack.Clone(); var res = new List<ACar>(); var model = new ACar(self); while (stack.Count > 0) { var m = stack[0]; AMove.ModelMove(model, m, new PassedInfo(), Bonuses, OilSlicks, Tires, Others); m.Times--; stack.Normalize(); res.Add(model.Clone()); } return res.ToArray(); }
public void PrepareOpponentsPath() { if (world.Tick < Const.Game.InitialFreezeDurationTicks) { return; } TimerStart(); var ways = Opponents.Select(GetWaySegments).ToArray(); #if DEBUG var segs = Opponents.Select(x => new Points()).ToArray(); #endif OpponentsCars = new ACar[Opponents.Length][]; for (var i = 0; i < Opponents.Length; i++) { if (ComputedPath.ContainsKey(Opponents[i].Id)) { OpponentsCars[i] = ComputedPath[Opponents[i].Id]; } else { OpponentsCars[i] = new ACar[MagicConst.OpponentsTicksPrediction]; OpponentsCars[i][0] = new ACar(Opponents[i]); for (var t = 1; t < MagicConst.OpponentsTicksPrediction; t++) { OpponentsCars[i][t] = OpponentsCars[i][t - 1].Clone(); _simulateOpponentMove(ways[i], OpponentsCars[i][t]); #if DEBUG segs[i].Add(new Point(OpponentsCars[i][t])); #endif } } } #if DEBUG foreach (var seg in segs) { Visualizer.SegmentsDrawQueue.Add(new object[] { Brushes.Indigo, seg, 0.0 }); } #endif TimerEndLog("PrepareOpponentsPath"); }
public double ComputeImportance(ACar model) { model = model.Clone(); var total = new PassedInfo(); foreach (var move in this) { for (var t = 0; t < move.Times; t++) { _modelMove(model, move, total); } } #if DEBUG if (ComputeTime() != total.Time) { throw new Exception("ComputeTime() != elapsedTime"); } #endif return(total.Time - total.Importance + Penalty); }
private void _simulateOpponentMove(Points pts, ACar car) { if (car.OutOfMap) { return; } if (pts.Count == 0) { Log("need more points!"); return; } var p = pts[0]; if (car.GetDistanceTo2(p) < 500 * 500) { pts.RemoveAt(0); _simulateOpponentMove(pts, car); return; } var turn = car.GetAngleTo(p); var power = 1.0; if (Math.Abs(turn) > 0.5) { power = 0.5; } if (Math.Abs(turn) > 1) { power = 0.3; } if (!ModelMove(car, new AMove { EnginePower = power, IsBrake = false, WheelTurn = TurnRound(turn) }, simpleMode: true)) { car.OutOfMap = true; } }
public ACar(ACar car) { X = car.X; Y = car.Y; Original = car.Original; Speed = car.Speed.Clone(); Angle = car.Angle; EnginePower = car.EnginePower; WheelTurn = car.WheelTurn; AngularSpeed = car.AngularSpeed; OutOfMap = car.OutOfMap; RemainingNitroTicks = car.RemainingNitroTicks; RemainingNitroCooldownTicks = car.RemainingNitroCooldownTicks; RemainingInactiveTicks = car.RemainingInactiveTicks; Width = car.Width; Height = car.Height; _carAccelerationUp = car._carAccelerationUp; _carAccelerationDown = car._carAccelerationDown; }
public static ACar[] GetCarPath(Car self, Moves stack) { if (stack == null) { return(null); } stack = stack.Clone(); var res = new List <ACar>(); var model = new ACar(self); while (stack.Count > 0) { var m = stack[0]; AMove.ModelMove(model, m, new PassedInfo(), Bonuses, OilSlicks, Tires, Others); m.Times--; stack.Normalize(); res.Add(model.Clone()); } return(res.ToArray()); }
public void Apply(Move move, ACar car) { move.EnginePower = EnginePower; move.IsBrake = IsBrake; move.WheelTurn = WheelTurn is Point?MyStrategy.TurnRound(car.GetAngleTo(WheelTurn as Point)) : Convert.ToDouble(WheelTurn); if (EnginePower < 0 && car.EnginePower > 0) { move.IsBrake = true; } else if (car.EnginePower < 0 && EnginePower > 0) { move.WheelTurn *= -1; move.IsBrake = true; } if (IsUseNitro) { move.IsUseNitro = IsUseNitro; } }
private void _validateLastSuccessStack() { if (_lastSuccessStack == null) { return; } var car = new ACar(Self); var stack = _lastSuccessStack.Clone(); var info = new PassedInfo(); while (stack.Count > 0) { if (!AMove.ModelMove(car, stack[0], info, new ABonus[] {}, new AOilSlick[] {}, new AProjectile[][] {}, new ACar[][] {})) { _lastSuccessStack = null; return; } stack[0].Times--; stack.Normalize(); } }
public static bool ModelMove(ACar car, AMove m, bool simpleMode = false, bool exactlyBorders = false) { var prevStateX = car.X; var prevStateY = car.Y; var prevStateAngle = car.Angle; var turn = m.WheelTurn is Point?TurnRound(car.GetAngleTo(m.WheelTurn as Point)) : Convert.ToDouble(m.WheelTurn); car.Move(m.EnginePower, turn, m.IsBrake, m.IsUseNitro, simpleMode); var ok = car.GetRect(0).All(p => !IntersectTail(p, exactlyBorders ? 0 : MagicConst.SafeMargin)); if (!ok) { // HACK car.X = prevStateX; car.Y = prevStateY; car.Angle = prevStateAngle; car.Speed = Point.Zero; car.AngularSpeed = 0; } return(ok); }
public static AProjectile[] GetProjectiles(ACar car) { if (car.Original.Type == CarType.Jeep) { return new[] { new AProjectile { Radius = Const.Game.TireRadius, Type = ProjectileType.Tire, X = car.X, Y = car.Y, Speed = Point.ByAngle(car.Angle) * Const.Game.TireInitialSpeed }}; } return new[] { 0.0, -Const.Game.SideWasherAngle, Const.Game.SideWasherAngle }.Select(angle => new AProjectile { Radius = Const.Game.WasherRadius, Type = ProjectileType.Washer, X = car.X, Y = car.Y, Speed = Point.ByAngle(angle + car.Angle) * Const.Game.WasherInitialSpeed }).ToArray(); }
public static AProjectile[] GetProjectiles(ACar car) { if (car.Original.Type == CarType.Jeep) { return(new[] { new AProjectile { Radius = Const.Game.TireRadius, Type = ProjectileType.Tire, X = car.X, Y = car.Y, Speed = Point.ByAngle(car.Angle) * Const.Game.TireInitialSpeed } }); } return(new[] { 0.0, -Const.Game.SideWasherAngle, Const.Game.SideWasherAngle }.Select(angle => new AProjectile { Radius = Const.Game.WasherRadius, Type = ProjectileType.Washer, X = car.X, Y = car.Y, Speed = Point.ByAngle(angle + car.Angle) * Const.Game.WasherInitialSpeed }).ToArray()); }
public bool Intersect(ACar car, double safeMargin) { return GetDistanceTo2(car) < Geom.Sqr(Radius + safeMargin); }
public static void Draw() { if (_form.InvokeRequired) { _form.BeginInvoke(new DrawDelegate(Draw), new object[] { }); return; } _renderTick++; if ((_renderTick - 1) % _myCarsCount != _myCarsCount - 1) return; var panel = _form.panel; _form.tickLabel.Text = MyStrategy.world.Tick + ""; var drawArea = new Bitmap(panel.Size.Width, panel.Size.Height); panel.Image = drawArea; _graphics = Graphics.FromImage(drawArea); if (_myCarsCount == 1) { _form.jeepRadioButton.Enabled = false; _form.buggyRadioButton.Enabled = false; LookUp(new Point(MyStrategy.world.Cars.FirstOrDefault(x => x.IsTeammate))); } else { LookUp( new Point( MyStrategy.world.Cars.FirstOrDefault( x => x.IsTeammate && (x.Type == CarType.Jeep && _form.jeepRadioButton.Checked || x.Type == CarType.Buggy && _form.buggyRadioButton.Checked)))); } //var myNextWp = MyStrategy.GetNextWayPoint(self); //FillRect(Brushes.Aqua, myNextWp.J * Const.TileSize, myNextWp.I * Const.TileSize, Const.TileSize, Const.TileSize); // tiles foreach (var tile in MyStrategy.MyTiles) { var margin = Const.TileMargin; var tsize = Const.TileSize; var dx = Const.TileSize*tile.J; var dy = Const.TileSize*tile.I; if (tile.Type == TileType.Unknown) FillRect(Brushes.DarkGray, dx, dy, tsize, tsize); if (tile.Type == TileType.Empty) FillRect(Brushes.Black, dx, dy, tsize, tsize); if (!tile.IsFreeLeft) FillRect(Brushes.Black, dx, dy, margin, tsize); if (!tile.IsFreeTop) FillRect(Brushes.Black, dx, dy, tsize, margin); if (!tile.IsFreeRight) FillRect(Brushes.Black, dx + tsize - margin, dy, margin, tsize); if (!tile.IsFreeBottom) FillRect(Brushes.Black, dx, dy + tsize - margin, tsize, margin); foreach (var part in tile.Parts) { switch (part.Type) { case TilePartType.Circle: FillCircle(Brushes.Black, part.Circle.X, part.Circle.Y, part.Circle.Radius); break; case TilePartType.Segment: DrawLine(Brushes.DarkRed, part.Start.X, part.Start.Y, part.End.X, part.End.Y, 1); break; default: throw new Exception("Unknown TilePartType"); } } } // Bonuses foreach (var bonus in MyStrategy.world.Bonuses) { var rect = new ABonus(bonus).GetRect(); for (var i = 0; i < 4; i++) { Brush brush; if (bonus.Type == BonusType.PureScore) brush = Brushes.OrangeRed; else if (bonus.Type == BonusType.RepairKit) brush = Brushes.LimeGreen; else if (bonus.Type == BonusType.OilCanister) brush = Brushes.DarkSlateGray; else if (bonus.Type == BonusType.NitroBoost) brush = Brushes.Blue; else if (bonus.Type == BonusType.AmmoCrate) brush = Brushes.DarkGoldenrod; else throw new Exception("Unknown BonusType"); DrawLine(brush, rect[i].X, rect[i].Y, rect[(i + 1) % 4].X, rect[(i + 1) % 4].Y, 2); } } // Cars foreach (var car in MyStrategy.world.Cars) { var isAvtive = DurabilityObserver.IsActive(car); var rect = new ACar(car).GetRectEx(isAvtive ? 0 : 1); for (var i = 0; i < 4; i++) { DrawLine(car.IsTeammate ? Brushes.Green : Brushes.Red, rect[i].X, rect[i].Y, rect[(i + 1)%4].X, rect[(i + 1)%4].Y, isAvtive ? 2 : 1); } var to = Point.ByAngle(car.Angle)*100 + new Point(car); DrawLine(Brushes.Black, car.X, car.Y, to.X, to.Y, car.Type == CarType.Buggy ? 2 : 6); DrawText("~" + car.ProjectileCount, 50, Brushes.Black, car.X, car.Y); } // Oil foreach (var stick in MyStrategy.world.OilSlicks) FillCircle(Brushes.Black, stick.X, stick.Y, stick.Radius); // Nitro foreach (var car in MyStrategy.world.Cars) { if (car.RemainingNitroTicks > 0) FillCircle(Brushes.Blue, car.X, car.Y, 40); } // Canisters foreach (var car in MyStrategy.world.Cars) { if (car.OilCanisterCount == 0) continue; var canisterPen = car.RemainingOilCooldownTicks == 0 ? Pens.DarkSlateGray : Pens.Lavender; var slick = new AOilSlick(new ACar(car)); DrawCircle(canisterPen, slick.X, slick.Y, slick.Radius); if (car.RemainingOiledTicks > 0) FillCircle(Brushes.Black, car.X, car.Y, 30); } // Projectiles foreach (var pr in MyStrategy.world.Projectiles) { FillCircle(Brushes.OrangeRed, pr.X, pr.Y, pr.Radius); } // Segments try { foreach (var _el in SegmentsDrawQueue) { var el = _el as object[]; var brush = el[0] as Brush; var line = el[1] as Points; var width = Convert.ToDouble(el[2]); for (var i = 1; i < line.Count; i++) DrawLine(brush, line[i - 1].X, line[i - 1].Y, line[i].X, line[i].Y, (float)width); } } catch (Exception) { } // Circles foreach (var el in CircleFillQueue) { var brush = el.Item1; var circle = el.Item2; FillCircle(brush, circle.X, circle.Y, circle.Radius); } CircleFillQueue.Clear(); SegmentsDrawQueue.Clear(); }
private void _validateLastSuccessStack() { if (_lastSuccessStack == null) return; var car = new ACar(Self); var stack = _lastSuccessStack.Clone(); var info = new PassedInfo(); while (stack.Count > 0) { if (!AMove.ModelMove(car, stack[0], info, new ABonus[] {}, new AOilSlick[] {}, new AProjectile[][] {}, new ACar[][] {})) { _lastSuccessStack = null; return; } stack[0].Times--; stack.Normalize(); } }
private void _carMoveFunc(ACar model, int from, int to, int step, AMove m, PassedInfo passed, CarCallback callback) { model = model.Clone(); passed = passed.Clone(); m.Times = 0; for (var t = 0; t < from; t++) { if (!_modelMove(model, m, passed)) return; m.Times++; } for (var t = from; t <= to; t += step) { _movesStack.Add(m); callback(model, passed); _movesStack.Pop(); for (var r = 0; r < step; r++) { if (!_modelMove(model, m, passed)) return; m.Times++; } } }
public static bool ModelMove(ACar car, AMove m, bool simpleMode = false, bool exactlyBorders = false) { var prevStateX = car.X; var prevStateY = car.Y; var prevStateAngle = car.Angle; var turn = m.WheelTurn is Point ? TurnRound(car.GetAngleTo(m.WheelTurn as Point)) : Convert.ToDouble(m.WheelTurn); car.Move(m.EnginePower, turn, m.IsBrake, m.IsUseNitro, simpleMode); var ok = car.GetRect(0).All(p => !IntersectTail(p, exactlyBorders ? 0 : MagicConst.SafeMargin)); if (!ok) { // HACK car.X = prevStateX; car.Y = prevStateY; car.Angle = prevStateAngle; car.Speed = Point.Zero; car.AngularSpeed = 0; } return ok; }
private void _simulateOpponentMove(Points pts, ACar car) { if (car.OutOfMap) return; if (pts.Count == 0) { Log("need more points!"); return; } var p = pts[0]; if (car.GetDistanceTo2(p) < 500 * 500) { pts.RemoveAt(0); _simulateOpponentMove(pts, car); return; } var turn = car.GetAngleTo(p); var power = 1.0; if (Math.Abs(turn) > 0.5) power = 0.5; if (Math.Abs(turn) > 1) power = 0.3; if (!ModelMove(car, new AMove {EnginePower = power, IsBrake = false, WheelTurn = TurnRound(turn)}, simpleMode: true)) { car.OutOfMap = true; } }
public void PrepareOpponentsPath() { if (world.Tick < Const.Game.InitialFreezeDurationTicks) return; TimerStart(); var ways = Opponents.Select(GetWaySegments).ToArray(); #if DEBUG var segs = Opponents.Select(x => new Points()).ToArray(); #endif OpponentsCars = new ACar[Opponents.Length][]; for (var i = 0; i < Opponents.Length; i++) { if (ComputedPath.ContainsKey(Opponents[i].Id)) OpponentsCars[i] = ComputedPath[Opponents[i].Id]; else { OpponentsCars[i] = new ACar[MagicConst.OpponentsTicksPrediction]; OpponentsCars[i][0] = new ACar(Opponents[i]); for (var t = 1; t < MagicConst.OpponentsTicksPrediction; t++) { OpponentsCars[i][t] = OpponentsCars[i][t - 1].Clone(); _simulateOpponentMove(ways[i], OpponentsCars[i][t]); #if DEBUG segs[i].Add(new Point(OpponentsCars[i][t])); #endif } } } #if DEBUG foreach (var seg in segs) Visualizer.SegmentsDrawQueue.Add(new object[] { Brushes.Indigo, seg, 0.0 }); #endif TimerEndLog("PrepareOpponentsPath"); }
public bool Intersect(ACar car, double safeMargin) { return(GetDistanceTo2(car) < Geom.Sqr(Radius + safeMargin)); }
private bool _modelMove(ACar car, AMove m, PassedInfo total) { return(AMove.ModelMove(car, m, total, MyStrategy.Bonuses, MyStrategy.OilSlicks, MyStrategy.Tires, MyStrategy.Others)); }
public static void Draw() { if (_form.InvokeRequired) { _form.BeginInvoke(new DrawDelegate(Draw), new object[] { }); return; } _renderTick++; if ((_renderTick - 1) % _myCarsCount != _myCarsCount - 1) { return; } var panel = _form.panel; _form.tickLabel.Text = MyStrategy.world.Tick + ""; var drawArea = new Bitmap(panel.Size.Width, panel.Size.Height); panel.Image = drawArea; _graphics = Graphics.FromImage(drawArea); if (_myCarsCount == 1) { _form.jeepRadioButton.Enabled = false; _form.buggyRadioButton.Enabled = false; LookUp(new Point(MyStrategy.world.Cars.FirstOrDefault(x => x.IsTeammate))); } else { LookUp( new Point( MyStrategy.world.Cars.FirstOrDefault( x => x.IsTeammate && (x.Type == CarType.Jeep && _form.jeepRadioButton.Checked || x.Type == CarType.Buggy && _form.buggyRadioButton.Checked)))); } //var myNextWp = MyStrategy.GetNextWayPoint(self); //FillRect(Brushes.Aqua, myNextWp.J * Const.TileSize, myNextWp.I * Const.TileSize, Const.TileSize, Const.TileSize); // tiles foreach (var tile in MyStrategy.MyTiles) { var margin = Const.TileMargin; var tsize = Const.TileSize; var dx = Const.TileSize * tile.J; var dy = Const.TileSize * tile.I; if (tile.Type == TileType.Unknown) { FillRect(Brushes.DarkGray, dx, dy, tsize, tsize); } if (tile.Type == TileType.Empty) { FillRect(Brushes.Black, dx, dy, tsize, tsize); } if (!tile.IsFreeLeft) { FillRect(Brushes.Black, dx, dy, margin, tsize); } if (!tile.IsFreeTop) { FillRect(Brushes.Black, dx, dy, tsize, margin); } if (!tile.IsFreeRight) { FillRect(Brushes.Black, dx + tsize - margin, dy, margin, tsize); } if (!tile.IsFreeBottom) { FillRect(Brushes.Black, dx, dy + tsize - margin, tsize, margin); } foreach (var part in tile.Parts) { switch (part.Type) { case TilePartType.Circle: FillCircle(Brushes.Black, part.Circle.X, part.Circle.Y, part.Circle.Radius); break; case TilePartType.Segment: DrawLine(Brushes.DarkRed, part.Start.X, part.Start.Y, part.End.X, part.End.Y, 1); break; default: throw new Exception("Unknown TilePartType"); } } } // Bonuses foreach (var bonus in MyStrategy.world.Bonuses) { var rect = new ABonus(bonus).GetRect(); for (var i = 0; i < 4; i++) { Brush brush; if (bonus.Type == BonusType.PureScore) { brush = Brushes.OrangeRed; } else if (bonus.Type == BonusType.RepairKit) { brush = Brushes.LimeGreen; } else if (bonus.Type == BonusType.OilCanister) { brush = Brushes.DarkSlateGray; } else if (bonus.Type == BonusType.NitroBoost) { brush = Brushes.Blue; } else if (bonus.Type == BonusType.AmmoCrate) { brush = Brushes.DarkGoldenrod; } else { throw new Exception("Unknown BonusType"); } DrawLine(brush, rect[i].X, rect[i].Y, rect[(i + 1) % 4].X, rect[(i + 1) % 4].Y, 2); } } // Cars foreach (var car in MyStrategy.world.Cars) { var isAvtive = DurabilityObserver.IsActive(car); var rect = new ACar(car).GetRectEx(isAvtive ? 0 : 1); for (var i = 0; i < 4; i++) { DrawLine(car.IsTeammate ? Brushes.Green : Brushes.Red, rect[i].X, rect[i].Y, rect[(i + 1) % 4].X, rect[(i + 1) % 4].Y, isAvtive ? 2 : 1); } var to = Point.ByAngle(car.Angle) * 100 + new Point(car); DrawLine(Brushes.Black, car.X, car.Y, to.X, to.Y, car.Type == CarType.Buggy ? 2 : 6); DrawText("~" + car.ProjectileCount, 50, Brushes.Black, car.X, car.Y); } // Oil foreach (var stick in MyStrategy.world.OilSlicks) { FillCircle(Brushes.Black, stick.X, stick.Y, stick.Radius); } // Nitro foreach (var car in MyStrategy.world.Cars) { if (car.RemainingNitroTicks > 0) { FillCircle(Brushes.Blue, car.X, car.Y, 40); } } // Canisters foreach (var car in MyStrategy.world.Cars) { if (car.OilCanisterCount == 0) { continue; } var canisterPen = car.RemainingOilCooldownTicks == 0 ? Pens.DarkSlateGray : Pens.Lavender; var slick = new AOilSlick(new ACar(car)); DrawCircle(canisterPen, slick.X, slick.Y, slick.Radius); if (car.RemainingOiledTicks > 0) { FillCircle(Brushes.Black, car.X, car.Y, 30); } } // Projectiles foreach (var pr in MyStrategy.world.Projectiles) { FillCircle(Brushes.OrangeRed, pr.X, pr.Y, pr.Radius); } // Segments try { foreach (var _el in SegmentsDrawQueue) { var el = _el as object[]; var brush = el[0] as Brush; var line = el[1] as Points; var width = Convert.ToDouble(el[2]); for (var i = 1; i < line.Count; i++) { DrawLine(brush, line[i - 1].X, line[i - 1].Y, line[i].X, line[i].Y, (float)width); } } } catch (Exception) { } // Circles foreach (var el in CircleFillQueue) { var brush = el.Item1; var circle = el.Item2; FillCircle(brush, circle.X, circle.Y, circle.Radius); } CircleFillQueue.Clear(); SegmentsDrawQueue.Clear(); }
public Moves Do(ACar car, Points pts) { // Проверка что данный путь был выбран if (_selectThisTick + 1 != MyStrategy.world.Tick) _lastSuccessStack = null; Self = car.Clone(); if (_lastCall == LastSuccess) LastSuccess = _lastCall; for (var t = 0; t < MyStrategy.world.Tick - _lastCall && _lastSuccessStack != null && _lastSuccessStack.Count > 0; t++) { _lastSuccessStack[0].Times--; _lastSuccessStack.Normalize(); } if (_lastSuccessStack != null && (_lastSuccessStack.Count == 0 || _useDist2 && _lastSuccessStack.ComputeTime() < 30)) _lastSuccessStack = null; _lastCall = MyStrategy.world.Tick; /* * Количество бонусов на расстоянии 0.5t * Если изменилось - пересчитывать сильно */ var bonusesCount05 = MyStrategy.Bonuses .Count(bonus => Self.GetDistanceTo(bonus) < Const.TileSize / 2); /* * Количество бонусов на расстоянии 2t * Если изменилось - чуть нужно пересчитать */ var bonusesCount2 = MyStrategy.Bonuses .Count( bonus => Self.GetDistanceTo(bonus) < Const.TileSize*2 && MyStrategy.CellDistance(Self, bonus) <= 2); // Если был success на прошлом тике, то продолжаем. Или каждые _interval тиков. if (Const.Game.InitialFreezeDurationTicks < MyStrategy.world.Tick && bonusesCount05 == _bonusesCount05 && LastSuccess < MyStrategy.world.Tick - 1 && (MyStrategy.world.Tick - (LastSuccess + 1))%_interval != 0) { _validateLastSuccessStack(); return _lastSuccessStack; } /* * Смотрим на шины, которые на расстоянии не более 6 тайлов */ var prevProj = _projCandidates; _projCandidates = MyStrategy.Tires .Where( proj => Self.GetDistanceTo(proj[0]) <= Const.TileSize * 6 && MyStrategy.CellDistance(Self, proj[0]) <= 6) .ToArray(); var extended = MyStrategy.ExtendWaySegments(pts, 50); _bruteWayPoints = extended.GetRange(0, Math.Min(_waypointsCount, extended.Count)).ToArray(); if (LastStageMove.IsUseNitro && _turnsCount(_bruteWayPoints) > 1) return null; #if DEBUG var bruteWayPoints = new Points(); bruteWayPoints.AddRange(_bruteWayPoints); Visualizer.SegmentsDrawQueue.Add(new object[]{ Brushes.Brown, bruteWayPoints, 0.0 }); #endif _needDist = Const.TileSize*0.5 - 3; _needDist2 = Const.TileSize - 3; _turnTo = _bruteWayPoints[_bruteWayPoints.Length - 1]; _turnTo2 = _bruteWayPoints[Math.Min(_bruteWayPoints.Length - 1, (int)(_bruteWayPoints.Length * 0.83))]; #if DEBUG Visualizer.CircleFillQueue.Add(new Tuple<Brush, ACircularUnit>(Brushes.OrangeRed, new ACircularUnit { X = _turnTo.X, Y = _turnTo.Y, Radius = 20})); Visualizer.CircleFillQueue.Add(new Tuple<Brush, ACircularUnit>(Brushes.Orange, new ACircularUnit { X = _turnTo2.X, Y = _turnTo2.Y, Radius = 20 })); #endif _patterns = Patterns.Select(pt => new PathPattern { From = pt.From, To = pt.To, Step = pt.Step, Move = pt.Move.Clone() }).ToArray(); foreach (var p in _patterns) { if (p.Move.WheelTurn is TurnPattern) { var turnPattern = p.Move.WheelTurn as TurnPattern; if (turnPattern.Pattern == TurnPatternType.ToNext) p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? -1 : 1; else if (turnPattern.Pattern == TurnPatternType.FromNext) p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? 1 : -1; } } _movesStack = new Moves(); _bestMovesStack = new Moves(); _bestTime = MyStrategy.Infinity; _bestImportance = 0; /* * Смотрим на бонусы, которые на расстоянии не более 4t * TODO: уменьшить приоритет бонусов, которые может быть возьмет другой (в.т.ч тиммейт) */ _bonusCandidates = MyStrategy.Bonuses .Where( bonus => MyStrategy.world.Tick > 270 && // Не смотреть на бонусы при старте!!! Self.GetDistanceTo(bonus) <= Const.TileSize * 4 && MyStrategy.CellDistance(Self, bonus) <= 4 ) .ToArray(); /* * Смотрим на лужи, которые на расстоянии не более 5 тайлов */ var prevSlicks = _slickCandidates; _slickCandidates = MyStrategy.OilSlicks .Where( slick => Self.GetDistanceTo(slick) <= Const.TileSize*5 && MyStrategy.CellDistance(Self, slick) <= 5 ) .ToArray(); /* * Пытаться объехать тех, которые * - Крашнулись * - Убиты * - Двигатель меньше чем на 0.5 мощности * - Двигаются по встречной * * - Если у меня нитро, или будет нитро * * - Своих */ var prevCars = _carCandidates; _carCandidates = MyStrategy.Others .Where(opp => opp[0].GetDistanceTo(Self) < Const.TileSize*9) .Where( opp => opp[0].Original.IsTeammate || MyStrategy.IsCrashed(opp[0].Original) || !DurabilityObserver.IsActive(opp[0].Original) || opp[0].EnginePower < 0.5 || Self.RemainingNitroTicks > 0 || Math.Abs(Geom.GetAngleBetween(Self.Speed, opp[0].Speed)) > Math.PI / 2 ) .Where(opp => MyStrategy.CellDistance(Self, opp[0]) <= 9) // 9 - потому что он может ехать по встречке .ToArray(); if (_cache != null) { for (var k = 0; k < _patterns.Length; k++) { var range = (prevSlicks == null || prevCars == null || prevProj == null || _bonusesCount2 != bonusesCount2 || prevSlicks.Length != _slickCandidates.Length || prevCars.Length != _carCandidates.Length || prevProj.Length != _projCandidates.Length) ? (k == 0 ? 6 : 4) : (k == 0 ? 6 : 2); if (_bonusesCount05 != bonusesCount05 || Special && k == 0) range = 10; _patterns[k].From = Math.Max(0, _cache[k].Times - range); _patterns[k].To = Math.Min(_patterns[k].To * 9 / 7, _cache[k].Times + range); _patterns[k].Step = 2; } } _bonusesCount05 = bonusesCount05; _bonusesCount2 = bonusesCount2; var wayPointRequired = false; for(var i = _bruteWayPoints.Length - 1; i >= 0; i--) { if (_bruteWayPoints[i].GetDistanceTo2(_turnTo) < _needDist*_needDist) { for (var j = 0; j < i; j++) wayPointRequired |= MyStrategy.GetNextWayPoint(Self.Original).Equals(MyStrategy.GetCell(_bruteWayPoints[j])); break; } } _doRecursive(Self, 0, new PassedInfo { WayPoint = !wayPointRequired }); _cache = null; if (_bestTime == MyStrategy.Infinity) return _lastSuccessStack; if (_bestMovesStack.ComputeTime() != _bestTime) throw new Exception("ComputeTime != BestTime"); LastSuccess = MyStrategy.world.Tick; _cache = _bestMovesStack.Clone(); if (_maxTicksInfo == null) _maxTicksInfo = new int[_bestMovesStack.Count]; for (var i = 0; i < _maxTicksInfo.Length; i++) _maxTicksInfo[i] = Math.Max(_maxTicksInfo[i], _bestMovesStack[i].Times); _bestMovesStack.Normalize(); _lastSuccessStack = _bestMovesStack.Clone(); return _bestMovesStack; }
public bool _modelMove(ACar car, AMove m, PassedInfo total) { return AMove.ModelMove(car, m, total, _bonusCandidates, _slickCandidates, _projCandidates, _carCandidates); }
/* * Проверка что кто-то стоит впереди * p2 p5 p3 p4 p1 * | | | | | * o-----------------o * | | * | | */ public bool IsSomeoneAhead(ACar car, int direction) { var carRect = car.GetRect(0); Point p1, p2; if (direction > 0) { p1 = carRect[0] + Point.ByAngle(car.Angle)*20; p2 = carRect[3] + Point.ByAngle(car.Angle)*20; } else { p1 = carRect[1] - Point.ByAngle(car.Angle) * 20; p2 = carRect[2] - Point.ByAngle(car.Angle) * 20; } var p3 = (p1 + p2)/2; var p4 = (p1 + p3)/2; var p5 = (p2 + p3)/2; return world.Cars.Select(x => new ACar(x).GetRect(0)).Any( rect => Geom.ContainPoint(rect, p1) || Geom.ContainPoint(rect, p2) || Geom.ContainPoint(rect, p3) || Geom.ContainPoint(rect, p4) || Geom.ContainPoint(rect, p5) ); }
private void _doRecursive(ACar model, int patternIndex, PassedInfo total) { model = model.Clone(); total = total.Clone(); if (patternIndex == _patterns.Length) { var m = LastStageMove.Clone(); m.WheelTurn = _turnTo.Clone(); if (m.IsUseNitro && (model.Speed.Length > 22 || m.EnginePower < 0)) return; var penalty = 0.0; for (var i = 0; ; i++) { if (i == 200 && m.EnginePower >= 0 || i == 250 && m.EnginePower < 0) return; var dst = _turnTo.GetDistanceTo2(model); if (dst < _needDist*_needDist) break; if (!_modelMove(model, m, total)) { if (_useDist2 && m.EnginePower <= 1 && !LastStageMove.IsUseNitro) { if (dst < _needDist2 * _needDist2) { penalty = MagicConst.SecondDistDangerCoeff; total.Importance -= penalty; m.Times++; break; } } return; } m.Times++; } if (!total.WayPoint) return; if (!MyStrategy.CheckVisibility(Self.Original, model, penalty > 0 ? _turnTo2 : _turnTo, 20)) return; if (model.EnginePower < 0) { penalty += MagicConst.BackMoveDangerCoeff; total.Importance -= MagicConst.BackMoveDangerCoeff; } if (total.Time - total.Importance < _bestTime - _bestImportance) { _bestTime = total.Time; _bestImportance = total.Importance; _bestMovesStack = _movesStack.Clone(); _bestMovesStack.Add(m); _bestMovesStack.Penalty = penalty; } return; } var pattern = _patterns[patternIndex]; _carMoveFunc(model, pattern.From, pattern.To, pattern.Step, pattern.Move.Clone(), total, (aCar, passed) => { // ReSharper disable once ConvertToLambdaExpression _doRecursive(aCar.Clone(), patternIndex + 1, passed.Clone()); }); }
public bool IntersectWith(ACar car, double safeMargin) { if (GetDistanceTo2(car) > Geom.Sqr(Const.CarDiagonalHalfLength + Const.CarDiagonalHalfLength)) return false; return Geom.PolygonsIntersect(GetRect(0), car.GetRect(safeMargin)); }
private void _doRecursive(ACar model, int patternIndex, PassedInfo total) { model = model.Clone(); total = total.Clone(); if (patternIndex == _patterns.Length) { var m = LastStageMove.Clone(); m.WheelTurn = _turnTo.Clone(); if (m.IsUseNitro && (model.Speed.Length > 22 || m.EnginePower < 0)) { return; } var penalty = 0.0; for (var i = 0; ; i++) { if (i == 200 && m.EnginePower >= 0 || i == 250 && m.EnginePower < 0) { return; } var dst = _turnTo.GetDistanceTo2(model); if (dst < _needDist * _needDist) { break; } if (!_modelMove(model, m, total)) { if (_useDist2 && m.EnginePower <= 1 && !LastStageMove.IsUseNitro) { if (dst < _needDist2 * _needDist2) { penalty = MagicConst.SecondDistDangerCoeff; total.Importance -= penalty; m.Times++; break; } } return; } m.Times++; } if (!total.WayPoint) { return; } if (!MyStrategy.CheckVisibility(Self.Original, model, penalty > 0 ? _turnTo2 : _turnTo, 20)) { return; } if (model.EnginePower < 0) { penalty += MagicConst.BackMoveDangerCoeff; total.Importance -= MagicConst.BackMoveDangerCoeff; } if (total.Time - total.Importance < _bestTime - _bestImportance) { _bestTime = total.Time; _bestImportance = total.Importance; _bestMovesStack = _movesStack.Clone(); _bestMovesStack.Add(m); _bestMovesStack.Penalty = penalty; } return; } var pattern = _patterns[patternIndex]; _carMoveFunc(model, pattern.From, pattern.To, pattern.Step, pattern.Move.Clone(), total, (aCar, passed) => { // ReSharper disable once ConvertToLambdaExpression _doRecursive(aCar.Clone(), patternIndex + 1, passed.Clone()); }); }
bool CheckBackMove(Point turnCenter) { const int ticksToCheck = 40; for (var power = -1; power <= 1; power += 2) { if (BackModeRemainTicks == 0 && PositionsHistory.Count > ticksToCheck) { if ( PositionsHistory[PositionsHistory.Count - 1].GetDistanceTo( PositionsHistory[PositionsHistory.Count - ticksToCheck]) < 20) { var model = new ACar(self) {EnginePower = -power}; var cnt = 0; for (var i = 0; i < 80; i++) if (ModelMove(model, new AMove {EnginePower = -power, IsBrake = false, WheelTurn = 0}, simpleMode: false, exactlyBorders: true)) cnt++; if (cnt < 25 || IsSomeoneAhead(new ACar(self), -power)) { BackModeRemainTicks = 50; BackModeTurn = self.GetAngleTo(turnCenter.X, turnCenter.Y) < 0 ? -power : power; BackModePower = power; break; } } } } if (BackModeRemainTicks > 0) { BackModeRemainTicks--; move.EnginePower = BackModePower; move.WheelTurn = BackModeTurn; return true; } return false; }
public Moves Do(ACar car, Points pts) { // Проверка что данный путь был выбран if (_selectThisTick + 1 != MyStrategy.world.Tick) { _lastSuccessStack = null; } Self = car.Clone(); if (_lastCall == LastSuccess) { LastSuccess = _lastCall; } for (var t = 0; t < MyStrategy.world.Tick - _lastCall && _lastSuccessStack != null && _lastSuccessStack.Count > 0; t++) { _lastSuccessStack[0].Times--; _lastSuccessStack.Normalize(); } if (_lastSuccessStack != null && (_lastSuccessStack.Count == 0 || _useDist2 && _lastSuccessStack.ComputeTime() < 30)) { _lastSuccessStack = null; } _lastCall = MyStrategy.world.Tick; /* * Количество бонусов на расстоянии 0.5t * Если изменилось - пересчитывать сильно */ var bonusesCount05 = MyStrategy.Bonuses .Count(bonus => Self.GetDistanceTo(bonus) < Const.TileSize / 2); /* * Количество бонусов на расстоянии 2t * Если изменилось - чуть нужно пересчитать */ var bonusesCount2 = MyStrategy.Bonuses .Count( bonus => Self.GetDistanceTo(bonus) < Const.TileSize * 2 && MyStrategy.CellDistance(Self, bonus) <= 2); // Если был success на прошлом тике, то продолжаем. Или каждые _interval тиков. if (Const.Game.InitialFreezeDurationTicks < MyStrategy.world.Tick && bonusesCount05 == _bonusesCount05 && LastSuccess < MyStrategy.world.Tick - 1 && (MyStrategy.world.Tick - (LastSuccess + 1)) % _interval != 0) { _validateLastSuccessStack(); return(_lastSuccessStack); } /* * Смотрим на шины, которые на расстоянии не более 6 тайлов */ var prevProj = _projCandidates; _projCandidates = MyStrategy.Tires .Where( proj => Self.GetDistanceTo(proj[0]) <= Const.TileSize * 6 && MyStrategy.CellDistance(Self, proj[0]) <= 6) .ToArray(); var extended = MyStrategy.ExtendWaySegments(pts, 50); _bruteWayPoints = extended.GetRange(0, Math.Min(_waypointsCount, extended.Count)).ToArray(); if (LastStageMove.IsUseNitro && _turnsCount(_bruteWayPoints) > 1) { return(null); } #if DEBUG var bruteWayPoints = new Points(); bruteWayPoints.AddRange(_bruteWayPoints); Visualizer.SegmentsDrawQueue.Add(new object[] { Brushes.Brown, bruteWayPoints, 0.0 }); #endif _needDist = Const.TileSize * 0.5 - 3; _needDist2 = Const.TileSize - 3; _turnTo = _bruteWayPoints[_bruteWayPoints.Length - 1]; _turnTo2 = _bruteWayPoints[Math.Min(_bruteWayPoints.Length - 1, (int)(_bruteWayPoints.Length * 0.83))]; #if DEBUG Visualizer.CircleFillQueue.Add(new Tuple <Brush, ACircularUnit>(Brushes.OrangeRed, new ACircularUnit { X = _turnTo.X, Y = _turnTo.Y, Radius = 20 })); Visualizer.CircleFillQueue.Add(new Tuple <Brush, ACircularUnit>(Brushes.Orange, new ACircularUnit { X = _turnTo2.X, Y = _turnTo2.Y, Radius = 20 })); #endif _patterns = Patterns.Select(pt => new PathPattern { From = pt.From, To = pt.To, Step = pt.Step, Move = pt.Move.Clone() }).ToArray(); foreach (var p in _patterns) { if (p.Move.WheelTurn is TurnPattern) { var turnPattern = p.Move.WheelTurn as TurnPattern; if (turnPattern.Pattern == TurnPatternType.ToNext) { p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? -1 : 1; } else if (turnPattern.Pattern == TurnPatternType.FromNext) { p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? 1 : -1; } } } _movesStack = new Moves(); _bestMovesStack = new Moves(); _bestTime = MyStrategy.Infinity; _bestImportance = 0; /* * Смотрим на бонусы, которые на расстоянии не более 4t * TODO: уменьшить приоритет бонусов, которые может быть возьмет другой (в.т.ч тиммейт) */ _bonusCandidates = MyStrategy.Bonuses .Where( bonus => MyStrategy.world.Tick > 270 && // Не смотреть на бонусы при старте!!! Self.GetDistanceTo(bonus) <= Const.TileSize * 4 && MyStrategy.CellDistance(Self, bonus) <= 4 ) .ToArray(); /* * Смотрим на лужи, которые на расстоянии не более 5 тайлов */ var prevSlicks = _slickCandidates; _slickCandidates = MyStrategy.OilSlicks .Where( slick => Self.GetDistanceTo(slick) <= Const.TileSize * 5 && MyStrategy.CellDistance(Self, slick) <= 5 ) .ToArray(); /* * Пытаться объехать тех, которые * - Крашнулись * - Убиты * - Двигатель меньше чем на 0.5 мощности * - Двигаются по встречной * * - Если у меня нитро, или будет нитро * * - Своих */ var prevCars = _carCandidates; _carCandidates = MyStrategy.Others .Where(opp => opp[0].GetDistanceTo(Self) < Const.TileSize * 9) .Where( opp => opp[0].Original.IsTeammate || MyStrategy.IsCrashed(opp[0].Original) || !DurabilityObserver.IsActive(opp[0].Original) || opp[0].EnginePower < 0.5 || Self.RemainingNitroTicks > 0 || Math.Abs(Geom.GetAngleBetween(Self.Speed, opp[0].Speed)) > Math.PI / 2 ) .Where(opp => MyStrategy.CellDistance(Self, opp[0]) <= 9) // 9 - потому что он может ехать по встречке .ToArray(); if (_cache != null) { for (var k = 0; k < _patterns.Length; k++) { var range = (prevSlicks == null || prevCars == null || prevProj == null || _bonusesCount2 != bonusesCount2 || prevSlicks.Length != _slickCandidates.Length || prevCars.Length != _carCandidates.Length || prevProj.Length != _projCandidates.Length) ? (k == 0 ? 6 : 4) : (k == 0 ? 6 : 2); if (_bonusesCount05 != bonusesCount05 || Special && k == 0) { range = 10; } _patterns[k].From = Math.Max(0, _cache[k].Times - range); _patterns[k].To = Math.Min(_patterns[k].To * 9 / 7, _cache[k].Times + range); _patterns[k].Step = 2; } } _bonusesCount05 = bonusesCount05; _bonusesCount2 = bonusesCount2; var wayPointRequired = false; for (var i = _bruteWayPoints.Length - 1; i >= 0; i--) { if (_bruteWayPoints[i].GetDistanceTo2(_turnTo) < _needDist * _needDist) { for (var j = 0; j < i; j++) { wayPointRequired |= MyStrategy.GetNextWayPoint(Self.Original).Equals(MyStrategy.GetCell(_bruteWayPoints[j])); } break; } } _doRecursive(Self, 0, new PassedInfo { WayPoint = !wayPointRequired }); _cache = null; if (_bestTime == MyStrategy.Infinity) { return(_lastSuccessStack); } if (_bestMovesStack.ComputeTime() != _bestTime) { throw new Exception("ComputeTime != BestTime"); } LastSuccess = MyStrategy.world.Tick; _cache = _bestMovesStack.Clone(); if (_maxTicksInfo == null) { _maxTicksInfo = new int[_bestMovesStack.Count]; } for (var i = 0; i < _maxTicksInfo.Length; i++) { _maxTicksInfo[i] = Math.Max(_maxTicksInfo[i], _bestMovesStack[i].Times); } _bestMovesStack.Normalize(); _lastSuccessStack = _bestMovesStack.Clone(); return(_bestMovesStack); }
void AlternativeMove(Points pts) { var car = new ACar(self); var backBruteRes = _doAndSelectBrute(BackBrutes, pts); if (backBruteRes.Item1 != -1) { BackBrutes[backBruteRes.Item1].SelectThis(); var mv = backBruteRes.Item2[backBruteRes.Item1]; if (mv.Count > 0) { mv[0].Apply(move, new ACar(self)); ComputedPath[self.Id] = GetCarPath(self, mv); #if DEBUG Visualizer.DrawWays(self, backBruteRes.Item2, backBruteRes.Item1); #endif return; } } // change points pts = GetAlternativeWaySegments(self); var turnCenter = pts[1]; var tmp = new ACar(self); var aa = tmp + tmp.Speed; if (Math.Abs(tmp.GetAngleTo(aa)) > Math.PI / 2) { move.EnginePower = 1; move.WheelTurn *= -1; return; } move.EnginePower = 1.0; if (car.GetDistanceTo(turnCenter) < 1.6 * Const.TileSize) { move.EnginePower = 0.8; } if (car.GetDistanceTo(turnCenter) < 1.0 * Const.TileSize) { if (GetSpeed(self) > 11) move.IsBrake = true; } move.WheelTurn = car.GetAngleTo(turnCenter); if (BAD_TESTING_STRATEGY) { if (turnCenter.GetDistanceTo(self) >= 7*Const.TileSize && Math.Abs(car.GetAngleTo(turnCenter)) < Math.PI/6) { move.IsUseNitro = true; } } }
public bool _modelMove(ACar car, AMove m, PassedInfo total) { return(AMove.ModelMove(car, m, total, _bonusCandidates, _slickCandidates, _projCandidates, _carCandidates)); }
public static bool ModelMove(ACar car, AMove m, PassedInfo total, ABonus[] bonusCandidates, AOilSlick[] slickCandidates, AProjectile[][] projCandidates, ACar[][] carCandidates) { double prevStateX = 0, prevStateY = 0, prevStateAngle = 0; if (m.RangesMode) { prevStateX = car.X; prevStateY = car.Y; prevStateAngle = car.Angle; } var turn = m.WheelTurn is Point?MyStrategy.TurnRound(car.GetAngleTo(m.WheelTurn as Point)) : Convert.ToDouble(m.WheelTurn); var isBreak = m.IsBrake; // если сдаю назад но кочусь вперед if (m.EnginePower < 0 && car.EnginePower > 0) { isBreak = true; } // если еду вперед но кочусь назад else if (car.EnginePower < 0 && m.EnginePower > 0) { turn *= -1; isBreak = true; } var simpleMode = total.Time > 41; var checking = !simpleMode || (MyStrategy.world.Tick + total.Time) % 4 == 0; car.Move(m.EnginePower, turn, isBreak, m.IsUseNitro, simpleMode); if (checking) { for (var i = 0; i < bonusCandidates.Length; i++) { if (total.Bonuses[i]) // бонус уже взят { continue; } var bonus = bonusCandidates[i]; if (car.TakeBonus(bonus)) { total.Importance += bonus.GetImportance(car.Original) * MagicConst.BonusImportanceCoeff; total.Bonuses[i] = true; } } if (!total.Slicks) // если не въехал ни в одну лужу { foreach (var slick in slickCandidates) { if (total.Slicks) { break; } slick.RemainingLifetime -= total.Time; if (slick.Intersect(car, 9)) { total.Importance -= slick.GetDanger() * MagicConst.OilSlickDangerCoeff * (car.RemainingNitroTicks > 0 ? 2 : 1); total.Slicks = true; } slick.RemainingLifetime += total.Time; } } if (projCandidates.Length > 0 && total.Time < projCandidates[0].Length) { for (var i = 0; i < projCandidates.Length; i++) { if (total.Projectiles[i]) { continue; } var proj = projCandidates[i][total.Time]; if (proj.Intersect(car, 5)) { total.Importance -= proj.GetDanger() * MagicConst.TireDangerCoeff; total.Projectiles[i] = true; } } } if (!total.Cars) { for (var i = 0; i < carCandidates.Length; i++) { if (total.Time >= carCandidates[i].Length) { continue; } var opp = carCandidates[i][total.Time]; if (car.IntersectWith(opp, opp.Original.IsTeammate ? 20 : 0)) { if ((car.Speed.Length > 8 || car.Original.IsTeammate) && MyStrategy.world.Tick > 400) { // чтобы не боялся протаранить на маленькой скорости total.Importance -= car.RemainingNitroTicks > 0 ? MagicConst.InactiveCarNitroDangerCoeff : MagicConst.InactiveCarDangerCoeff; } total.Cars = true; break; } } } } total.Time++; var res = true; if (checking) { // проверка на стены res = car.GetRectEx().All(p => !MyStrategy.IntersectTail(p, m.SafeMargin)); // проверка что можно проехать точно возле стены if (!res && car.RemainingNitroTicks == 0 && m.ExactlyMargin < m.SafeMargin && car.GetRectEx().All(p => !MyStrategy.IntersectTail(p, m.ExactlyMargin))) { if (!total.ExactlyBorder) { total.Importance -= MagicConst.ExactlyBorderDangerCoeff; } total.ExactlyBorder = true; res = true; } // проверка что можно проскользнуть по стене if (!m.RangesMode && !res && car.RemainingNitroTicks == 0 && m.ExtraMargin < m.ExactlyMargin && car.GetRectEx().All(p => !MyStrategy.IntersectTail(p, total.Time < 20 ? -2 : m.ExtraMargin))) { if (!total.OutOfBoreder) { total.Importance -= MagicConst.OutOfBorederDangerCoeff; total.OutOfBoreder = true; } res = true; } if (!total.WayPoint) { total.WayPoint = MyStrategy.GetNextWayPoint(car.Original).Equals(MyStrategy.GetCell(car)); } if (!res && m.RangesMode) { res = true; // HACK car.X = prevStateX; car.Y = prevStateY; car.Angle = prevStateAngle; car.Speed = Point.Zero; car.AngularSpeed = 0; } } return(res); }