bool TrySubstitute(AHock hock) { if (!IsFinal() || hock.Speed.Length > Game.MaxSpeedToAllowSubstitute || !IsInSubstArea(hock) || hock.Base.RemainingCooldownTicks > 0 || hock.Base.RemainingKnockdownTicks > 0 ) { return(false); } var maxStamina = MyRest .Select(x => x.Stamina) .Max(); var maxStrength = MyRest .Where(x => Eq(maxStamina, x.Stamina)) .Select(x => x.Strength) .Max(); var to = Hockeyists.FirstOrDefault(x => Eq(x.Stamina, maxStamina) && Eq(x.Strength, maxStrength)); if (to == null || maxStamina < hock.Stamina) { return(false); } move.Action = ActionType.Substitute; move.TeammateIndex = to.TeammateIndex; return(true); }
double ProbabStrikeAfter(int swingTime, Hockeyist self, IEnumerable <MoveAction> actions, ActionType actionType) { var I = new AHock(self); if (Math.Abs(My.NetFront - I.X) < RinkWidth / 3) { return(0.0); } var power = GetPower(I, swingTime); var totalTime = 0; var opps = Hockeyists .Where(x => !x.IsTeammate && IsInGame(x)) .Select(x => new AHock(x)) .ToArray(); var goalie = Get(OppGoalie); foreach (var action in actions) { for (var i = 0; i < action.Ticks; i++) { GoalieMove(goalie, 1, I.PuckPos()); I.Move(action.SpeedUp, action.Turn); if (!Chase(opps, I)) { return(0.0); } } totalTime += action.Ticks; } var passAngle = PassAngleNorm(I.GetAngleTo(GetStrikePoint())); return(StrikeProbability(I, power, goalie, totalTime, actionType, passAngle, null)); }
public bool TryStrikeWithoutTakeIfSwinging(AHock _hock, APuck _pk) { var hock = _hock.Clone(); var pk = _pk.Clone(); var bestProbab = 0.0; var swTime = Inf; for (var sw = 0; sw <= Game.MaxEffectiveSwingTicks; sw++) { if (CanStrike(hock, pk)) { var pr = StrikeProbability(hock, GetPower(hock, sw + hock.Base.SwingTicks), pk.Goalie, -1, ActionType.Strike, 0, pk); if (pr > bestProbab) { bestProbab = pr; swTime = sw; } } hock.Move(0, 0); pk.Move(1); } if (swTime == Inf) { return(false); } if (swTime == 0) { move.Action = ActionType.Strike; } return(true); }
Pair<Point, int> GetSubstitutePoint(AHock hock) { Point bestPoint = null; var selDir = 0; var minTicks = Inf; for (var x = Game.RinkLeft; x <= Game.RinkRight; x += RinkWidth/100) { if (MyLeft() && x > RinkCenter.X - 100 || MyRight() && x < RinkCenter.X + 100) continue; var to = new Point(x, Game.RinkTop); var up = GetTicksToUp(hock, to); var down = GetTicksToDown(hock, to); if (up < minTicks) { minTicks = up; selDir = 1; bestPoint = to; } if (down < minTicks) { minTicks = down; selDir = -1; bestPoint = to; } } return new Pair<Point, int>(bestPoint, selDir); }
public static double GetPower(AHock self, int swingTime) { var res = Math.Min(Game.MaxEffectiveSwingTicks, swingTime) * 0.25 / Game.MaxEffectiveSwingTicks + 0.75; res = res * self.AStrength / 100; return(res); }
private bool StrikePrimitiveValidate(AHock striker) { var puckPos = striker.PuckPos(); if (Math.Abs(puckPos.X - Opp.NetFront) > RinkWidth / 3 * 2) { return(false); } if (Math.Abs(puckPos.X - Opp.NetFront) < 3.5 * HoRadius) { return(false); } if (MyRight() && Math.Cos(striker.Angle) > 0) { return(false); } if (MyLeft() && Math.Cos(striker.Angle) < 0) { return(false); } return(true); }
Pair <Point, int> GetSubstitutePoint(AHock hock) { Point bestPoint = null; var selDir = 0; var minTicks = Inf; for (var x = Game.RinkLeft; x <= Game.RinkRight; x += RinkWidth / 100) { if (MyLeft() && x > RinkCenter.X - 100 || MyRight() && x < RinkCenter.X + 100) { continue; } var to = new Point(x, Game.RinkTop); var up = GetTicksToUp(hock, to); var down = GetTicksToDown(hock, to); if (up < minTicks) { minTicks = up; selDir = 1; bestPoint = to; } if (down < minTicks) { minTicks = down; selDir = -1; bestPoint = to; } } return(new Pair <Point, int>(bestPoint, selDir)); }
public APuck GetPassPuck(AHock striker, double PassPower, double PassAngle, Point goalie) { var puckSpeedAbs = striker.AStrength / 100 * Game.PassPowerFactor * Game.StruckPuckInitialSpeedFactor * PassPower + striker.Speed.Length * Math.Cos(striker.Angle + PassAngle - striker.Speed.GetAngle()); var puckAngle = AngleNormalize(PassAngle + striker.Angle); var puckSpeed = new Point(puckAngle)*puckSpeedAbs; return new APuck(striker.PuckPos(), puckSpeed, goalie); }
bool TryPass(AHock striker) { if (striker.Base.RemainingCooldownTicks != 0) { return(false); } TimerStart(); const int passAnglesCount = 7; double minTime = Inf, bestAngle = 0.0, bestPower = 0.0; foreach (var power in new[] { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0 }) { for (var passDir = -1; passDir <= 1; passDir += 2) { for (var absPassAngle = 0.0; absPassAngle <= Game.PassSector / 2; absPassAngle += Game.PassSector / 2 / passAnglesCount) { var passAngle = absPassAngle * passDir; var pk = GetPassPuck(striker, power, passAngle, Get(OppGoalie)); // TODO: проверять на автогол var on = GetFirstOnPuck(new[] { striker.Base }, pk, IsFinal(), 100, false); pk.Move(300); if (APuck.PuckLastTicks < on.First) { continue; } var toHock = new AHock(Get(on.Second)); if (!toHock.Base.IsTeammate) { continue; } var time = on.First; if (IsWaitingSwing(toHock)) { time /= 5; } if (time < minTime) { minTime = time; bestAngle = passAngle; bestPower = power; } } } } Log("TryPass " + TimerStop()); if (minTime >= Inf - Eps) { return(false); } move.Action = ActionType.Pass; move.PassAngle = bestAngle; move.PassPower = bestPower; return(true); }
bool Strike(AHock striker, double strikePower, Point goalie, ActionType actionType, double passAngle, Point puckPos) { var pk = actionType == ActionType.Strike ? GetStrikePuck(striker, strikePower, goalie, puckPos) : GetPassPuck(striker, 1, passAngle, goalie); return(PuckPrimitiveValidate(pk) && pk.Move(300, true) == 1); }
public APuck GetPassPuck(AHock striker, double PassPower, double PassAngle, Point goalie) { var puckSpeedAbs = striker.AStrength / 100 * Game.PassPowerFactor * Game.StruckPuckInitialSpeedFactor * PassPower + striker.Speed.Length * Math.Cos(striker.Angle + PassAngle - striker.Speed.GetAngle()); var puckAngle = AngleNormalize(PassAngle + striker.Angle); var puckSpeed = new Point(puckAngle) * puckSpeedAbs; return(new APuck(striker.PuckPos(), puckSpeed, goalie)); }
bool IsWaitingSwing(AHock hock) { var str = GetStrikePoint(); if (Math.Abs(hock.GetAngleTo(str)) > Deg(60)) return false; return Math.Abs(My.NetFront - hock.X) > RinkWidth / 3 && (hock.Y < Game.GoalNetTop || hock.Y > Game.GoalNetTop + Game.GoalNetHeight); }
public bool FindPath(Hockeyist self, Point to, Point lookAt) { if (lookAt == null) { return(StopOn(new AHock(self), to)); } var okDist = HoRadius * 1.5; var minTime = Inf; var selTurn = 0.0; var selSpUp = 0.0; for (var dir = -1; dir <= 1; dir += 2) { var hock = new AHock(self); for (var ticksDirect = 0; ticksDirect < 100; ticksDirect++) { var curTime = ticksDirect; var ho = hock.Clone(); while (Math.Abs(ho.GetAngleTo(lookAt)) > Deg(8)) { ho.Move(0, TurnNorm(ho.GetAngleTo(lookAt), ho.AAgility)); curTime++; } if (curTime < minTime && ho.GetDistanceTo(to) < okDist) { minTime = curTime; if (ticksDirect == 0) { selSpUp = 0.0; selTurn = TurnNorm(ho.GetAngleTo(lookAt), hock.AAgility); } else if (dir > 0) { selTurn = self.GetAngleTo(to.X, to.Y); selSpUp = GetSpeedTo(selTurn); } else { selTurn = RevAngle(self.GetAngleTo(to.X, to.Y)); selSpUp = -GetSpeedTo(selTurn); } } if (dir > 0) { GetTicksToUpN(hock, to, 0, 1); } else { GetTicksToDownN(hock, to, 0, 1); } } } move.SpeedUp = selSpUp; move.Turn = selTurn; return(minTime != Inf); }
public int GetTicksTo(Point to, Hockeyist my, bool tryDown = true) { var ho = new AHock(my); var up = GetTicksToUp(ho, to); var down = tryDown ? GetTicksToDown(ho, to) : Inf; if (up <= down) return up; return -down; }
APuck GetStrikePuck(AHock striker, double strikePower, Point goalie, Point puckPos) { var strikerDirection = new Point(striker.Angle); var speedAngleStriker = striker.Speed.GetAngle(); var puckSpeed = 20.0 * strikePower + striker.Speed.Length * Math.Cos(striker.Angle - speedAngleStriker); var puckSpeedDirection = strikerDirection * puckSpeed; return(new APuck(puckPos ?? striker.PuckPos(), puckSpeedDirection, goalie)); }
public int GetTicksToUpN(AHock ho, Point to, double takePuck = -1, int limit = 500) { var result = 0; for (; result < limit && (takePuck < 0 ? !CanStrike(ho, to) : ho.GetDistanceTo2(to) > takePuck*takePuck); result++) { ho.MoveTo(to); } return result; }
public Point FindWayPoint(Hockeyist self) { var okDist = 5 * HoRadius; var bestTime = Inf; Point sel = null; //TimerStart(); var bot = Hockeyists.Count(x => !x.IsTeammate && IsInGame(x) && x.Y > RinkCenter.Y); var top = Hockeyists.Count(x => !x.IsTeammate && IsInGame(x) && x.Y <= RinkCenter.Y); foreach (Point p in WayPoints.ToArray().OrderBy(x => ((Point)x).GetDistanceTo(self)).Take(10)) { var I = new AHock(self); if (p.GetDistanceTo2(I) <= okDist * okDist || MyRight() && I.X < p.X || MyLeft() && I.X > p.X) { continue; } var cands = Hockeyists .Where(x => !x.IsTeammate && IsInGame(x)) .Select(x => new AHock(x)).ToArray(); var time = 0; var ok = true; while (p.GetDistanceTo2(I) > okDist * okDist && ok) { I.MoveTo(p); foreach (var c in cands) { c.MoveTo(I); if (CanStrike(c, I.PuckPos()) || // достанет шайбу CanStrike(c, I) || // достанет меня I.GetDistanceTo2(c) <= 2 * HoRadius * 2 * HoRadius // столкнется со мной ) { ok = false; break; } } time++; } if (ok) { if (p.Y > RinkCenter.Y && bot > top || p.Y <= RinkCenter.Y && top > bot) { time *= 3; } if (time < bestTime) { bestTime = time; sel = p.Clone(); } } } //Log("FindWayPoint " + TimerStop()); return(sel); }
// Проверка движение хоккеиста void Research3(Hockeyist self) { var range = TurnRange(new AHock(self).AAgility); move.Turn = range / 2; move.SpeedUp = 0.8; var pl = new AHock(self); pl.Move(0.8, range / 2, 20); }
public int GetTicksToUpN(AHock ho, Point to, double takePuck = -1, int limit = 500) { var result = 0; for (; result < limit && (takePuck <0 ? !CanStrike(ho, to) : ho.GetDistanceTo2(to)> takePuck * takePuck); result++) { ho.MoveTo(to); } return(result); }
bool IsWaitingSwing(AHock hock) { var str = GetStrikePoint(); if (Math.Abs(hock.GetAngleTo(str)) > Deg(60)) { return(false); } return(Math.Abs(My.NetFront - hock.X) > RinkWidth / 3 && (hock.Y < Game.GoalNetTop || hock.Y > Game.GoalNetTop + Game.GoalNetHeight)); }
public int GetTicksToDownN(AHock ho, Point to, double takePuck = -1, int limit = 300) { var result = 0; for (; result < limit && (takePuck < 0 ? !CanStrike(ho, to) : ho.GetDistanceTo2(to) > takePuck * takePuck); result++) { var turn = RevAngle(ho.GetAngleTo(to)); var speedUp = -GetSpeedTo(turn); ho.Move(speedUp, TurnNorm(turn, ho.AAgility)); } return result >= limit ? Inf : result; }
Point PuckMove(int ticks, APuck pk, AHock hock) { if (hock == null) { pk.Move(ticks); return new Point(pk); } if (Math.Abs(hock.GetAngleTo(hock + hock.Speed)) < Deg(15) && hock.Speed.Length > 2) hock.Move(1, 0, ticks); // TODO return hock.PuckPos(); }
public Point FindWayPoint(Hockeyist self) { var okDist = 5*HoRadius; var bestTime = Inf; Point sel = null; //TimerStart(); var bot = Hockeyists.Count(x => !x.IsTeammate && IsInGame(x) && x.Y > RinkCenter.Y); var top = Hockeyists.Count(x => !x.IsTeammate && IsInGame(x) && x.Y <= RinkCenter.Y); foreach (Point p in WayPoints.ToArray().OrderBy(x => ((Point) x).GetDistanceTo(self)).Take(10)) { var I = new AHock(self); if (p.GetDistanceTo2(I) <= okDist*okDist || MyRight() && I.X < p.X || MyLeft() && I.X > p.X) continue; var cands = Hockeyists .Where(x => !x.IsTeammate && IsInGame(x)) .Select(x => new AHock(x)).ToArray(); var time = 0; var ok = true; while (p.GetDistanceTo2(I) > okDist*okDist && ok) { I.MoveTo(p); foreach (var c in cands) { c.MoveTo(I); if (CanStrike(c, I.PuckPos()) // достанет шайбу || CanStrike(c, I) // достанет меня || I.GetDistanceTo2(c) <= 2*HoRadius*2*HoRadius // столкнется со мной ) { ok = false; break; } } time++; } if (ok) { if (p.Y > RinkCenter.Y && bot > top || p.Y <= RinkCenter.Y && top > bot) time *= 3; if (time < bestTime) { bestTime = time; sel = p.Clone(); } } } //Log("FindWayPoint " + TimerStop()); return sel; }
public int GetTicksToDownN(AHock ho, Point to, double takePuck = -1, int limit = 300) { var result = 0; for (; result < limit && (takePuck <0 ? !CanStrike(ho, to) : ho.GetDistanceTo2(to)> takePuck * takePuck); result++) { var turn = RevAngle(ho.GetAngleTo(to)); var speedUp = -GetSpeedTo(turn); ho.Move(speedUp, TurnNorm(turn, ho.AAgility)); } return(result >= limit ? Inf : result); }
bool Chase(IEnumerable <AHock> opps, AHock I) { foreach (var opp in opps) { opp.MoveTo(I); if (CanStrike(opp, I) || CanStrike(opp, I.PuckPos())) { return(false); } } return(true); }
public int GetTicksTo(Point to, Hockeyist my, bool tryDown = true) { var ho = new AHock(my); var up = GetTicksToUp(ho, to); var down = tryDown ? GetTicksToDown(ho, to) : Inf; if (up <= down) { return(up); } return(-down); }
// определение силы паса bool ResearchPass(AHock hock) { if (puck.OwnerHockeyistId == hock.Base.Id && hock.CoolDown == 0) { var t = GetPassPuck(hock, 1, 0, null); move.Action = ActionType.Pass; move.PassPower = 1; move.PassAngle = 0; return(true); } return(false); }
int GetTicksToPuckDirect(AHock _hock, APuck _puck, int limit) { var hock = _hock.Clone(); var pk = _puck.Clone(); int result; for (result = 0; result < limit && !CanStrike(hock, pk); result++) { hock.MoveTo(pk); pk.Move(1); } return result; }
bool StopOn(AHock _hock, Point to) { var minTime = Inf; var selTurn = 0.0; var selSpUp = 0.0; for (var dir = -1; dir <= 1; dir += 2) { var hock = _hock.Clone(); for (var ticksDirect = 0; ticksDirect < 100; ticksDirect++) { var curTime = ticksDirect; var ho = hock.Clone(); var prevSpeed = ho.Speed.Length; for (var _ = 0; _ < 100; _++) { var spUp = dir < 0 ? 1 : -1; ho.Move(spUp, 0.0); var curSpeed = ho.Speed.Length; if (curSpeed > prevSpeed) { break; } prevSpeed = curSpeed; curTime++; } if (curTime < minTime && prevSpeed < Game.MaxSpeedToAllowSubstitute && IsInSubstArea(ho)) { minTime = curTime; if (ticksDirect == 0) { selSpUp = dir < 0 ? 1 : -1; selTurn = 0; } else if (dir > 0) { selTurn = _hock.GetAngleTo(to.X, to.Y); selSpUp = GetSpeedTo(selTurn); } else { selTurn = RevAngle(_hock.GetAngleTo(to.X, to.Y)); selSpUp = -GetSpeedTo(selTurn); } } hock.MoveTo(to, dir); } } move.Turn = selTurn; move.SpeedUp = selSpUp; return(minTime < Inf); }
Point PuckMove(int ticks, APuck pk, AHock hock) { if (hock == null) { pk.Move(ticks); return(new Point(pk)); } if (Math.Abs(hock.GetAngleTo(hock + hock.Speed)) < Deg(15) && hock.Speed.Length > 2) { hock.Move(1, 0, ticks); // TODO } return(hock.PuckPos()); }
int GetTicksToPuckDirect(AHock _hock, APuck _puck, int limit) { var hock = _hock.Clone(); var pk = _puck.Clone(); int result; for (result = 0; result < limit && !CanStrike(hock, pk); result++) { hock.MoveTo(pk); pk.Move(1); } return(result); }
public bool FindPath(Hockeyist self, Point to, Point lookAt) { if (lookAt == null) return StopOn(new AHock(self), to); var okDist = HoRadius * 1.5; var minTime = Inf; var selTurn = 0.0; var selSpUp = 0.0; for (var dir = -1; dir <= 1; dir += 2) { var hock = new AHock(self); for (var ticksDirect = 0; ticksDirect < 100; ticksDirect++) { var curTime = ticksDirect; var ho = hock.Clone(); while (Math.Abs(ho.GetAngleTo(lookAt)) > Deg(8)) { ho.Move(0, TurnNorm(ho.GetAngleTo(lookAt), ho.AAgility)); curTime++; } if (curTime < minTime && ho.GetDistanceTo(to) < okDist) { minTime = curTime; if (ticksDirect == 0) { selSpUp = 0.0; selTurn = TurnNorm(ho.GetAngleTo(lookAt), hock.AAgility); } else if (dir > 0) { selTurn = self.GetAngleTo(to.X, to.Y); selSpUp = GetSpeedTo(selTurn); } else { selTurn = RevAngle(self.GetAngleTo(to.X, to.Y)); selSpUp = -GetSpeedTo(selTurn); } } if (dir > 0) GetTicksToUpN(hock, to, 0, 1); else GetTicksToDownN(hock, to, 0, 1); } } move.SpeedUp = selSpUp; move.Turn = selTurn; return minTime != Inf; }
public int MoveHockTo(AHock ho, Point to) { var result = 0; for (; !CanStrike(ho, to); result++) { ho.MoveTo(to); if (result > 500) { return(result); } } return(result); }
bool StrikeWithDev(AHock striker, double strikePower, Point goalie, ActionType actionType, double passAngle, double dev, Point puckPos) { var result = false; if (actionType == ActionType.Strike) { striker.Angle += dev; } if (Strike(striker, strikePower, goalie, actionType, passAngle + dev, puckPos)) { result = true; } if (actionType == ActionType.Strike) { striker.Angle -= dev; } return(result); }
bool NeedTrySubstitute(AHock hock) { if (!IsFinal()) { return(false); } var maxStamina = Hockeyists .Where(x => x.State == HockeyistState.Resting && x.IsTeammate) .Select(x => x.Stamina) .Max(); var to = Hockeyists.FirstOrDefault(x => Eq(x.Stamina, maxStamina)); if (to == null || maxStamina * 0.8 < hock.Stamina) { return(false); } return(true); }
double StrikeProbability(AHock striker, double strikePower, Point goalie, int leftTime, ActionType actionType, double passAngle, Point puckPos) { if (striker.CoolDown != 0) return 0.0; if (!Strike(striker, strikePower, goalie, actionType, passAngle, puckPos)) return 0.0; const int iters = 5; var deviation = (actionType == ActionType.Strike ? Game.StrikeAngleDeviation : Game.PassAngleDeviation)*100/striker.ADexterity; var range = deviation*2; double upL = 0, upR = range; for (var it = 0; it < iters; it++) { var c = (upL + upR)/2; if (StrikeWithDev(striker, strikePower, goalie, actionType, passAngle, c, puckPos)) upL = c; else upR = c; } double downL = -range, downR = 0; for (var it = 0; it < iters; it++) { var c = (downL + downR) / 2; if (StrikeWithDev(striker, strikePower, goalie, actionType, passAngle, c, puckPos)) downR = c; else downL = c; } double result = GaussIntegral(downL, upR, deviation); // Проверка что шайбу перехватят: if (leftTime != -1) { var pk = actionType == ActionType.Strike ? GetStrikePuck(striker, strikePower, goalie, puckPos) : GetPassPuck(striker, 1, passAngle, goalie); var opps = Hockeyists .Where(x => !x.IsTeammate && IsInGame(x)) .Select(x => new AHock(x)).ToArray(); pk.Clone().Move(300, true); var time = APuck.PuckLastTicks; for (var t = -leftTime; t < time; t++) { foreach (var opp in opps) { var hisTurn = TurnNorm(opp.GetAngleTo(pk), opp.AAgility); opp.Move(0.0, hisTurn); if (CanStrike(opp, pk)) { var pTake = (75.0 + Math.Max(opp.ADexterity, opp.AAgility) - pk.Speed.Length/20*100)/100; return result*(1 - pTake); } } if (t >= 0) pk.Move(1); } } return result; }
private bool StrikePrimitiveValidate(AHock striker) { var puckPos = striker.PuckPos(); if (Math.Abs(puckPos.X - Opp.NetFront) > RinkWidth/3*2) return false; if (Math.Abs(puckPos.X - Opp.NetFront) < 3.5*HoRadius) return false; if (MyRight() && Math.Cos(striker.Angle) > 0) return false; if (MyLeft() && Math.Cos(striker.Angle) < 0) return false; return true; }
// определение силы паса bool ResearchPass(AHock hock) { if (puck.OwnerHockeyistId == hock.Base.Id && hock.CoolDown == 0) { var t = GetPassPuck(hock, 1, 0, null); move.Action = ActionType.Pass; move.PassPower = 1; move.PassAngle = 0; return true; } return false; }
bool TryPass(AHock striker) { if (striker.Base.RemainingCooldownTicks != 0) return false; TimerStart(); const int passAnglesCount = 7; double minTime = Inf, bestAngle = 0.0, bestPower = 0.0; foreach (var power in new[] { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0 }) { for (var passDir = -1; passDir <= 1; passDir += 2) { for (var absPassAngle = 0.0; absPassAngle <= Game.PassSector/2; absPassAngle += Game.PassSector/2/passAnglesCount) { var passAngle = absPassAngle*passDir; var pk = GetPassPuck(striker, power, passAngle, Get(OppGoalie)); // TODO: проверять на автогол var on = GetFirstOnPuck(new[] {striker.Base}, pk, IsFinal(), 100, false); pk.Move(300); if (APuck.PuckLastTicks < on.First) continue; var toHock = new AHock(Get(on.Second)); if (!toHock.Base.IsTeammate) continue; var time = on.First; if (IsWaitingSwing(toHock)) time /= 5; if (time < minTime) { minTime = time; bestAngle = passAngle; bestPower = power; } } } } Log("TryPass " + TimerStop()); if (minTime >= Inf - Eps) return false; move.Action = ActionType.Pass; move.PassAngle = bestAngle; move.PassPower = bestPower; return true; }
public static bool CanStrike(AHock hock, Point to) { return(Math.Abs(hock.GetAngleTo(to)) <= Game.StickSector / 2 && hock.GetDistanceTo2(to) <= Game.StickLength * Game.StickLength && hock.KnockDown == 0 && hock.CoolDown == 0); }
public void Move(Hockeyist self, World world, Game game, Move move) { if (self.State == HockeyistState.Resting) return; ShowWindow(); // // fill globals _strikePoint = null; Hockeyists = world.Hockeyists; MyRest = Hockeyists.Where(x => x.IsTeammate && x.State == HockeyistState.Resting).ToArray(); this.puck = world.Puck; this.move = move; World = world; Game = game; Opp = world.GetOpponentPlayer(); My = world.GetMyPlayer(); RinkWidth = game.RinkRight - game.RinkLeft; RinkHeight = game.RinkBottom - game.RinkTop; OppGoalie = Hockeyists.FirstOrDefault(x => !x.IsTeammate && x.Type == HockeyistType.Goalie); MyGoalie = Hockeyists.FirstOrDefault(x => x.IsTeammate && x.Type == HockeyistType.Goalie); HoRadius = self.Radius; RinkCenter = new Point(game.RinkLeft + RinkWidth/2, game.RinkTop + RinkHeight/2); PuckRadius = puck.Radius; var friends = Hockeyists .Where(x => x.IsTeammate && x.Id != self.Id && x.Type != HockeyistType.Goalie && x.State != HockeyistState.Resting) .ToArray(); var friend1 = friends.Count() < 2 || friends[0].TeammateIndex < friends[1].TeammateIndex ? friends[0] : friends[1]; var friend2 = friends.Count() > 1 ? friends[0].TeammateIndex < friends[1].TeammateIndex ? friends[1] : friends[0] : null; FillWayPoints(); // // if (Game.OvertimeTickCount == 200) // костыль чтобы пройти верификацию return; TimerStart(); var hock = new AHock(self); var needSubst = NeedTrySubstitute(hock); if (My.IsJustMissedGoal || My.IsJustScoredGoal) { SubstSignal = false; StayOn(self, GetSubstitutePoint(hock).First, null); TrySubstitute(hock); } else { var range = TurnRange(hock.AAgility); move.SpeedUp = Inf; if (self.State == HockeyistState.Swinging && self.Id != puck.OwnerHockeyistId) { if (!TryStrikeWithoutTakeIfSwinging(hock, new APuck(puck, OppGoalie))) move.Action = ActionType.CancelStrike; } else if (puck.OwnerHockeyistId == self.Id) { var wait = Inf; double selTurn = 0, selSpeedUp = 0; var willSwing = false; var maxProb = 0.15; var selAction = ActionType.Strike; TimerStart(); if (self.State != HockeyistState.Swinging) { var spUps = self.RemainingCooldownTicks == 0 || Math.Abs(self.X - My.NetFront) < RinkWidth / 2 ? (Math.Abs(self.X - Opp.NetFront) < RinkWidth / 3 ? new[] { 0.0, 1.0 } : new[] { 1.0 }) : new[] { 1.0, 0.5, 0.0, -0.5 }; var moveDirBase = MyRight() && self.Y > RinkCenter.Y || MyLeft() && self.Y < RinkCenter.Y ? 1 : -1; // если не замахнулся for (var ticks = 0; ticks < 50; ticks++) { // если буду замахиваться (ТО В КОНЦЕ!!!), то нужно подождать минимум game.SwingActionCooldownTicks const int turns = 4; for (var moveDir = -1; moveDir <= 1; moveDir += 2) { for (var moveTurn = 0.0; moveTurn - Eps <= range; moveTurn += range/turns) { var turn = moveDir*moveTurn; foreach (var spUp in spUps) { if (moveDir == moveDirBase || spUp <= Eps && IsFinal()) { var end = ticks + game.SwingActionCooldownTicks; var start = Math.Max(0, end - game.MaxEffectiveSwingTicks); // когда начинаем замахиваться var p = ProbabStrikeAfter(end - start, self, new[] { new MoveAction {Ticks = start, SpeedUp = spUp, Turn = turn}, new MoveAction {Ticks = end - start, SpeedUp = 0, Turn = 0}, }, ActionType.Strike); if (p > maxProb) { wait = start; willSwing = true; maxProb = p; selTurn = turn; selSpeedUp = spUp; selAction = ActionType.Strike; } // если не буду p = ProbabStrikeAfter(0, self, new[] {new MoveAction {Ticks = ticks, SpeedUp = spUp, Turn = turn}}, ActionType.Strike); if (p > maxProb) { wait = ticks; willSwing = false; maxProb = p; selTurn = turn; selSpeedUp = spUp; selAction = ActionType.Strike; } // если пасом p = ProbabStrikeAfter(0, self, new[] {new MoveAction {Ticks = ticks, SpeedUp = spUp, Turn = turn}}, ActionType.Pass); if (p > maxProb) { wait = ticks; willSwing = false; maxProb = p; selTurn = turn; selSpeedUp = spUp; selAction = ActionType.Pass; } } } } } } } else { // если уже замахнулся for (var ticks = Math.Max(0, game.SwingActionCooldownTicks - self.SwingTicks); ticks < 80; ticks++) { var p = ProbabStrikeAfter(ticks + self.SwingTicks, self, new[] {new MoveAction {Ticks = ticks, SpeedUp = 0, Turn = 0}}, ActionType.Strike); if (p > maxProb) { wait = ticks; willSwing = true; maxProb = p; selAction = ActionType.Strike; } } } Log("STRIKE " + TimerStop()); if (wait < Inf) { SubstSignal = true; } drawInfo.Enqueue((wait == Inf ? 0 : maxProb) + ""); if (!willSwing && self.State == HockeyistState.Swinging) { move.Action = ActionType.CancelStrike; } else if (willSwing && wait == 0 && self.State != HockeyistState.Swinging) { move.Action = ActionType.Swing; } else if (wait == Inf) { var wayPoint = FindWayPoint(self); if (wayPoint == null) { needPassQueue.Enqueue(Get(self)); if (!TryPass(hock)) { var pt = Math.Abs(Opp.NetFront - self.X) < RinkWidth/3 ? Get(friend2 == null || (MyLeft() ? friend2.X > friend1.X : friend2.X < friend1.X) ? friend1 : friend2) : GetStrikePoint(); DoMove(self, pt, 1); } } else { DoMove(self, wayPoint, 1); } } else if (wait == 0) { move.Action = selAction; if (selAction == ActionType.Pass) { move.PassPower = 1; move.PassAngle = PassAngleNorm(hock.GetAngleTo(GetStrikePoint())); } } else { move.SpeedUp = selSpeedUp; move.Turn = selTurn; } } else if (puck.OwnerPlayerId != -1 || !TryStrikeWithoutTake(hock, new APuck(puck, OppGoalie))) { var owner = Hockeyists.FirstOrDefault(x => x.Id == puck.OwnerHockeyistId); var pk = new APuck(puck, MyGoalie) {IsDefend = true}; if (puck.OwnerPlayerId == Opp.Id && (CanStrike(self, owner) || CanStrike(self, puck))) { // попытаться выбить move.Action = ActionType.Strike; } else if (puck.OwnerPlayerId != self.PlayerId && CanStrike(self, puck)) { // проверяем что не летит в чужие ворота var cpk = new APuck(puck, OppGoalie); if (cpk.Move(200, true) == 0) { if (pk.Move(200, goalCheck: true) == 1) // если вратарь не отобьёт move.Action = ActionType.Strike; else move.Action = ActionType.TakePuck; } } else { var toPuck = GoToPuck(self, null); var toPuck1 = GoToPuck(friend1, null); var toPuck2 = friend2 == null ? null : GoToPuck(friend2, null); if (friend2 != null && toPuck1.Third < toPuck2.Third) { Swap(ref friend1, ref friend2); Swap(ref toPuck1, ref toPuck2); } var def = GetDefendPos2(); var have = puck.OwnerPlayerId == My.Id; // 1 - дольше всего идет до шайбы var net = new Point(My.NetFront, RinkCenter.Y); double ii = net.GetDistanceTo(self) < 300 ? 1.0 : 1.0; double jj = net.GetDistanceTo(friend1) < 300 ? 1.0 : 1.0; var myFirst = GetFirstOnPuck(new[] {self}, new APuck(puck, OppGoalie), true, 100, false).Second == (friend2 == null ? -1 : friend2.Id); if (have ? (friend2 == null || ii*GetTicksTo(def, self) < jj*GetTicksTo(def, friend1)) // если я ближе, то иду на ворота : toPuck.Third/ii > toPuck1.Third/jj) // если я дольше всего, то иду на ворота { if (needSubst && (SubstSignal || puck.OwnerPlayerId != Opp.Id && self.Y <= Game.RinkTop + 0.666 * RinkHeight || self.Y <= Game.SubstitutionAreaHeight + Game.RinkTop)) { if (TrySubstitute(hock)) SubstSignal = false; else StayOn(self, GetSubstitutePoint(hock).First, null); } else { StayOn(self, def, Get(puck)); } } // иначе 1 идет на воротаpuck.OwnerPlayerId != My.Id else if (friend2 == null || (puck.OwnerPlayerId != My.Id && ( toPuck.Third < toPuck2.Third //|| Math.Abs(Opp.NetFront - puck.X) < RinkWidth / 2 // шайба не у нас и на чужой половине || !myFirst ))) { var bestTime = Inf; double bestTurn = 0.0; var needTime = GetFirstOnPuck(Hockeyists.Where(x => x.IsTeammate), new APuck(puck, OppGoalie), true, -1).First; var lookAt = new Point(Opp.NetFront, RinkCenter.Y); for (var turn = -range; turn <= range; turn += range / 10) { var I = hock.Clone(); var P = new APuck(puck, OppGoalie); for (var t = 0; t < needTime - 10 && t < 70; t++) { if (CanStrike(I, P)) { var cl = I.Clone(); var tm = GetTicksToUp(cl, lookAt) + t; if (tm < bestTime) { bestTime = tm; bestTurn = turn; } } I.Move(0, turn); P.Move(1); } } var i = hock.Clone(); var direct = MoveHockTo(i, toPuck.First); direct += MoveHockTo(i, lookAt); if (bestTime < direct && bestTime < Inf) { move.Turn = bestTurn; move.SpeedUp = 0.0; } DoMove(self, toPuck.First, toPuck.Second); } else { if (needSubst && (SubstSignal || puck.OwnerPlayerId != Opp.Id && self.Y <= RinkCenter.Y || self.Y <= Game.SubstitutionAreaHeight + Game.RinkTop)) { if (TrySubstitute(hock)) SubstSignal = false; else StayOn(self, GetSubstitutePoint(hock).First, null); } else { var c1 = new Point(RinkCenter.X, Game.RinkTop + 2*HoRadius); var c2 = new Point(RinkCenter.X, Game.RinkBottom - 2*HoRadius); var c = c1.GetDistanceTo(puck) > c2.GetDistanceTo(puck) ? c1 : c2; var s = GetStrikePoint(); StayOn(self, c, s); } } } } if (Eq(move.SpeedUp, Inf)) move.SpeedUp = 1; } Log(self.TeammateIndex + " >>>>>>>>>>>> " + TimerStop()); if (move.Action != ActionType.None) Log(move.Action); #if DEBUG draw(); Thread.Sleep(8); #endif drawInfo.Clear(); needPassQueue.Clear(); }
bool TrySubstitute(AHock hock) { if (!IsFinal() || hock.Speed.Length > Game.MaxSpeedToAllowSubstitute || !IsInSubstArea(hock) || hock.Base.RemainingCooldownTicks > 0 || hock.Base.RemainingKnockdownTicks > 0 ) return false; var maxStamina = MyRest .Select(x => x.Stamina) .Max(); var maxStrength = MyRest .Where(x => Eq(maxStamina, x.Stamina)) .Select(x => x.Strength) .Max(); var to = Hockeyists.FirstOrDefault(x => Eq(x.Stamina, maxStamina) && Eq(x.Strength, maxStrength)); if (to == null || maxStamina < hock.Stamina) return false; move.Action = ActionType.Substitute; move.TeammateIndex = to.TeammateIndex; return true; }
public bool TryStrikeWithoutTakeIfSwinging(AHock _hock, APuck _pk) { var hock = _hock.Clone(); var pk = _pk.Clone(); var bestProbab = 0.0; var swTime = Inf; for (var sw = 0; sw <= Game.MaxEffectiveSwingTicks; sw++) { if (CanStrike(hock, pk)) { var pr = StrikeProbability(hock, GetPower(hock, sw + hock.Base.SwingTicks), pk.Goalie, -1, ActionType.Strike, 0, pk); if (pr > bestProbab) { bestProbab = pr; swTime = sw; } } hock.Move(0, 0); pk.Move(1); } if (swTime == Inf) return false; if (swTime == 0) move.Action = ActionType.Strike; return true; }
public int GetTicksToUp(AHock ho, Point to, double takePuck = -1, int limit = 500) { return GetTicksToUpN(ho.Clone(), to, takePuck, limit); }
public bool TryStrikeWithoutTake(AHock _hock, APuck _pk) { if (!StrikePrimitiveValidate(_hock)) { return(false); } TimerStart(); var moveDirBase = MyRight() && _hock.Y > RinkCenter.Y || MyLeft() && _hock.Y < RinkCenter.Y ? 1 : -1; var bestTurn = 0.0; var bestSpUp = 0.0; var bestProbab = 0.0; var bestWait = Inf; var swTime = 0; var range = TurnRange(_hock.AAgility); const int turns = 9; const int spUps = 8; for (var moveDir = -1; moveDir <= 1; moveDir += 2) { for (var moveTurn = 0.0; moveTurn <= range + Eps; moveTurn += range / turns) { var turn = moveDir * moveTurn; for (var spUp = 0.0; spUp <= 1.0; spUp += 1.0 / spUps) { var hock = _hock.Clone(); var pk = _pk.Clone(); var ticksWait = 0; for (var startDist2 = hock.GetDistanceTo2(pk); !CanStrike(hock, pk) && ticksWait < 150; ticksWait++) { if (moveDir == moveDirBase || IsFinal() && moveTurn < range / 2) { var I = hock.Clone(); var p = pk.Clone(); for (var sw = 0; sw <= Game.MaxEffectiveSwingTicks; sw++) { if (sw >= Game.SwingActionCooldownTicks && CanStrike(I, p)) { var pr = StrikeProbability(I, GetPower(I, sw), p.Goalie, -1, ActionType.Strike, 0, p); if (pr > bestProbab) { bestProbab = pr; bestTurn = turn; bestSpUp = spUp; bestWait = ticksWait; swTime = sw; } } I.Move(0, 0); p.Move(1); } } hock.Move(spUp, turn); pk.Move(1); var dist2 = hock.GetDistanceTo2(pk); if (dist2 > startDist2) { break; } startDist2 = dist2; } if (CanStrike(hock, pk)) { var p = StrikeProbability(hock, GetPower(hock, 0), pk.Goalie, -1, ActionType.Strike, 0, pk); if (p > bestProbab) { bestProbab = p; bestTurn = turn; bestSpUp = spUp; bestWait = ticksWait; swTime = 0; } } } } } Log("SWING " + TimerStop()); if (bestWait == Inf) { return(false); } move.Turn = bestTurn; move.SpeedUp = bestSpUp; if (bestWait == 0) { move.Action = swTime == 0 ? ActionType.Strike : ActionType.Swing; } return(true); }
bool StopOn(AHock _hock, Point to) { var minTime = Inf; var selTurn = 0.0; var selSpUp = 0.0; for (var dir = -1; dir <= 1; dir += 2) { var hock = _hock.Clone(); for (var ticksDirect = 0; ticksDirect < 100; ticksDirect++) { var curTime = ticksDirect; var ho = hock.Clone(); var prevSpeed = ho.Speed.Length; for(var _ = 0; _ < 100; _++) { var spUp = dir < 0 ? 1 : -1; ho.Move(spUp, 0.0); var curSpeed = ho.Speed.Length; if (curSpeed > prevSpeed) break; prevSpeed = curSpeed; curTime++; } if (curTime < minTime && prevSpeed < Game.MaxSpeedToAllowSubstitute && IsInSubstArea(ho)) { minTime = curTime; if (ticksDirect == 0) { selSpUp = dir < 0 ? 1 : -1; selTurn = 0; } else if (dir > 0) { selTurn = _hock.GetAngleTo(to.X, to.Y); selSpUp = GetSpeedTo(selTurn); } else { selTurn = RevAngle(_hock.GetAngleTo(to.X, to.Y)); selSpUp = -GetSpeedTo(selTurn); } } hock.MoveTo(to, dir); } } move.Turn = selTurn; move.SpeedUp = selSpUp; return minTime < Inf; }
public Tuple<Point, int, int> GoToPuck(Hockeyist my, APuck pk, int ticksLimit = 300, bool tryDown = true) { if (my.Id == puck.OwnerHockeyistId) return new Tuple<Point, int, int>(null, 0, 0); if (ticksLimit == -1) ticksLimit = 300; const int noBs = 100; var res = Inf; var dir = 1; var owner = Hockeyists.FirstOrDefault(x => x.Id == puck.OwnerHockeyistId); var ho = owner == null ? null : new AHock(owner); if (pk == null) pk = new APuck(puck, OppGoalie); else ho = null; var result = new Point(pk); int tLeft = 0, tRight = ticksLimit; var pks = new APuck[tRight + 1]; var hhs = new AHock[tRight + 1]; pks[0] = pk.Clone(); hhs[0] = ho; for (var i = 1; i <= tRight; i++) { pks[i] = pks[i - 1].Clone(); hhs[i] = ho == null ? null : hhs[i - 1].Clone(); PuckMove(1, pks[i], hhs[i]); } while (ticksLimit > noBs && tLeft <= tRight) { var c = (tLeft + tRight)/2; var needTicks = GetTicksTo(PuckMove(0, pks[c], hhs[c]), my, tryDown); if (Math.Abs(needTicks) < c) { tRight = c - 1; res = c; result = PuckMove(0, pks[c], hhs[c]); dir = needTicks >= 0 ? 1 : -1; } else { tLeft = c + 1; } } const int by = 10; for (var c = 0; c <= noBs && c <= ticksLimit; c += c < by ? 1 : by) { var needTicks = GetTicksTo(PuckMove(0, pks[c], hhs[c]), my, tryDown); if (Math.Abs(needTicks) <= c) { for (var i = 0; i < by; i++, c--) { if (Math.Abs(needTicks) <= c) { res = c; result = PuckMove(0, pks[c], hhs[c]); dir = needTicks >= 0 ? 1 : -1; } } break; } } return new Tuple<Point, int, int>(result, dir, res); }
bool StrikeWithDev(AHock striker, double strikePower, Point goalie, ActionType actionType, double passAngle, double dev, Point puckPos) { var result = false; if (actionType == ActionType.Strike) striker.Angle += dev; if (Strike(striker, strikePower, goalie, actionType, passAngle + dev, puckPos)) result = true; if (actionType == ActionType.Strike) striker.Angle -= dev; return result; }
bool Chase(IEnumerable<AHock> opps, AHock I) { foreach (var opp in opps) { opp.MoveTo(I); if (CanStrike(opp, I) || CanStrike(opp, I.PuckPos())) return false; } return true; }
public void Move(Hockeyist self, World world, Game game, Move move) { if (self.State == HockeyistState.Resting) { return; } ShowWindow(); // // fill globals _strikePoint = null; Hockeyists = world.Hockeyists; MyRest = Hockeyists.Where(x => x.IsTeammate && x.State == HockeyistState.Resting).ToArray(); this.puck = world.Puck; this.move = move; World = world; Game = game; Opp = world.GetOpponentPlayer(); My = world.GetMyPlayer(); RinkWidth = game.RinkRight - game.RinkLeft; RinkHeight = game.RinkBottom - game.RinkTop; OppGoalie = Hockeyists.FirstOrDefault(x => !x.IsTeammate && x.Type == HockeyistType.Goalie); MyGoalie = Hockeyists.FirstOrDefault(x => x.IsTeammate && x.Type == HockeyistType.Goalie); HoRadius = self.Radius; RinkCenter = new Point(game.RinkLeft + RinkWidth / 2, game.RinkTop + RinkHeight / 2); PuckRadius = puck.Radius; var friends = Hockeyists .Where(x => x.IsTeammate && x.Id != self.Id && x.Type != HockeyistType.Goalie && x.State != HockeyistState.Resting) .ToArray(); var friend1 = friends.Count() < 2 || friends[0].TeammateIndex < friends[1].TeammateIndex ? friends[0] : friends[1]; var friend2 = friends.Count() > 1 ? friends[0].TeammateIndex < friends[1].TeammateIndex ? friends[1] : friends[0] : null; FillWayPoints(); // // if (Game.OvertimeTickCount == 200) // костыль чтобы пройти верификацию { return; } TimerStart(); var hock = new AHock(self); var needSubst = NeedTrySubstitute(hock); if (My.IsJustMissedGoal || My.IsJustScoredGoal) { SubstSignal = false; StayOn(self, GetSubstitutePoint(hock).First, null); TrySubstitute(hock); } else { var range = TurnRange(hock.AAgility); move.SpeedUp = Inf; if (self.State == HockeyistState.Swinging && self.Id != puck.OwnerHockeyistId) { if (!TryStrikeWithoutTakeIfSwinging(hock, new APuck(puck, OppGoalie))) { move.Action = ActionType.CancelStrike; } } else if (puck.OwnerHockeyistId == self.Id) { var wait = Inf; double selTurn = 0, selSpeedUp = 0; var willSwing = false; var maxProb = 0.15; var selAction = ActionType.Strike; TimerStart(); if (self.State != HockeyistState.Swinging) { var spUps = self.RemainingCooldownTicks == 0 || Math.Abs(self.X - My.NetFront) < RinkWidth / 2 ? (Math.Abs(self.X - Opp.NetFront) < RinkWidth / 3 ? new[] { 0.0, 1.0 } : new[] { 1.0 }) : new[] { 1.0, 0.5, 0.0, -0.5 }; var moveDirBase = MyRight() && self.Y > RinkCenter.Y || MyLeft() && self.Y < RinkCenter.Y ? 1 : -1; // если не замахнулся for (var ticks = 0; ticks < 50; ticks++) { // если буду замахиваться (ТО В КОНЦЕ!!!), то нужно подождать минимум game.SwingActionCooldownTicks const int turns = 4; for (var moveDir = -1; moveDir <= 1; moveDir += 2) { for (var moveTurn = 0.0; moveTurn - Eps <= range; moveTurn += range / turns) { var turn = moveDir * moveTurn; foreach (var spUp in spUps) { if (moveDir == moveDirBase || spUp <= Eps && IsFinal()) { var end = ticks + game.SwingActionCooldownTicks; var start = Math.Max(0, end - game.MaxEffectiveSwingTicks); // когда начинаем замахиваться var p = ProbabStrikeAfter(end - start, self, new[] { new MoveAction { Ticks = start, SpeedUp = spUp, Turn = turn }, new MoveAction { Ticks = end - start, SpeedUp = 0, Turn = 0 }, }, ActionType.Strike); if (p > maxProb) { wait = start; willSwing = true; maxProb = p; selTurn = turn; selSpeedUp = spUp; selAction = ActionType.Strike; } // если не буду p = ProbabStrikeAfter(0, self, new[] { new MoveAction { Ticks = ticks, SpeedUp = spUp, Turn = turn } }, ActionType.Strike); if (p > maxProb) { wait = ticks; willSwing = false; maxProb = p; selTurn = turn; selSpeedUp = spUp; selAction = ActionType.Strike; } // если пасом p = ProbabStrikeAfter(0, self, new[] { new MoveAction { Ticks = ticks, SpeedUp = spUp, Turn = turn } }, ActionType.Pass); if (p > maxProb) { wait = ticks; willSwing = false; maxProb = p; selTurn = turn; selSpeedUp = spUp; selAction = ActionType.Pass; } } } } } } } else { // если уже замахнулся for (var ticks = Math.Max(0, game.SwingActionCooldownTicks - self.SwingTicks); ticks < 80; ticks++) { var p = ProbabStrikeAfter(ticks + self.SwingTicks, self, new[] { new MoveAction { Ticks = ticks, SpeedUp = 0, Turn = 0 } }, ActionType.Strike); if (p > maxProb) { wait = ticks; willSwing = true; maxProb = p; selAction = ActionType.Strike; } } } Log("STRIKE " + TimerStop()); if (wait < Inf) { SubstSignal = true; } drawInfo.Enqueue((wait == Inf ? 0 : maxProb) + ""); if (!willSwing && self.State == HockeyistState.Swinging) { move.Action = ActionType.CancelStrike; } else if (willSwing && wait == 0 && self.State != HockeyistState.Swinging) { move.Action = ActionType.Swing; } else if (wait == Inf) { var wayPoint = FindWayPoint(self); if (wayPoint == null) { needPassQueue.Enqueue(Get(self)); if (!TryPass(hock)) { var pt = Math.Abs(Opp.NetFront - self.X) < RinkWidth / 3 ? Get(friend2 == null || (MyLeft() ? friend2.X > friend1.X : friend2.X < friend1.X) ? friend1 : friend2) : GetStrikePoint(); DoMove(self, pt, 1); } } else { DoMove(self, wayPoint, 1); } } else if (wait == 0) { move.Action = selAction; if (selAction == ActionType.Pass) { move.PassPower = 1; move.PassAngle = PassAngleNorm(hock.GetAngleTo(GetStrikePoint())); } } else { move.SpeedUp = selSpeedUp; move.Turn = selTurn; } } else if (puck.OwnerPlayerId != -1 || !TryStrikeWithoutTake(hock, new APuck(puck, OppGoalie))) { var owner = Hockeyists.FirstOrDefault(x => x.Id == puck.OwnerHockeyistId); var pk = new APuck(puck, MyGoalie) { IsDefend = true }; if (puck.OwnerPlayerId == Opp.Id && (CanStrike(self, owner) || CanStrike(self, puck))) { // попытаться выбить move.Action = ActionType.Strike; } else if (puck.OwnerPlayerId != self.PlayerId && CanStrike(self, puck)) { // проверяем что не летит в чужие ворота var cpk = new APuck(puck, OppGoalie); if (cpk.Move(200, true) == 0) { if (pk.Move(200, goalCheck: true) == 1) // если вратарь не отобьёт { move.Action = ActionType.Strike; } else { move.Action = ActionType.TakePuck; } } } else { var toPuck = GoToPuck(self, null); var toPuck1 = GoToPuck(friend1, null); var toPuck2 = friend2 == null ? null : GoToPuck(friend2, null); if (friend2 != null && toPuck1.Third < toPuck2.Third) { Swap(ref friend1, ref friend2); Swap(ref toPuck1, ref toPuck2); } var def = GetDefendPos2(); var have = puck.OwnerPlayerId == My.Id; // 1 - дольше всего идет до шайбы var net = new Point(My.NetFront, RinkCenter.Y); double ii = net.GetDistanceTo(self) < 300 ? 1.0 : 1.0; double jj = net.GetDistanceTo(friend1) < 300 ? 1.0 : 1.0; var myFirst = GetFirstOnPuck(new[] { self }, new APuck(puck, OppGoalie), true, 100, false).Second == (friend2 == null ? -1 : friend2.Id); if (have ? (friend2 == null || ii * GetTicksTo(def, self) < jj * GetTicksTo(def, friend1)) // если я ближе, то иду на ворота : toPuck.Third / ii > toPuck1.Third / jj) // если я дольше всего, то иду на ворота { if (needSubst && (SubstSignal || puck.OwnerPlayerId != Opp.Id && self.Y <= Game.RinkTop + 0.666 * RinkHeight || self.Y <= Game.SubstitutionAreaHeight + Game.RinkTop)) { if (TrySubstitute(hock)) { SubstSignal = false; } else { StayOn(self, GetSubstitutePoint(hock).First, null); } } else { StayOn(self, def, Get(puck)); } } // иначе 1 идет на воротаpuck.OwnerPlayerId != My.Id else if (friend2 == null || (puck.OwnerPlayerId != My.Id && ( toPuck.Third < toPuck2.Third //|| Math.Abs(Opp.NetFront - puck.X) < RinkWidth / 2 // шайба не у нас и на чужой половине || !myFirst ))) { var bestTime = Inf; double bestTurn = 0.0; var needTime = GetFirstOnPuck(Hockeyists.Where(x => x.IsTeammate), new APuck(puck, OppGoalie), true, -1).First; var lookAt = new Point(Opp.NetFront, RinkCenter.Y); for (var turn = -range; turn <= range; turn += range / 10) { var I = hock.Clone(); var P = new APuck(puck, OppGoalie); for (var t = 0; t < needTime - 10 && t < 70; t++) { if (CanStrike(I, P)) { var cl = I.Clone(); var tm = GetTicksToUp(cl, lookAt) + t; if (tm < bestTime) { bestTime = tm; bestTurn = turn; } } I.Move(0, turn); P.Move(1); } } var i = hock.Clone(); var direct = MoveHockTo(i, toPuck.First); direct += MoveHockTo(i, lookAt); if (bestTime < direct && bestTime < Inf) { move.Turn = bestTurn; move.SpeedUp = 0.0; } DoMove(self, toPuck.First, toPuck.Second); } else { if (needSubst && (SubstSignal || puck.OwnerPlayerId != Opp.Id && self.Y <= RinkCenter.Y || self.Y <= Game.SubstitutionAreaHeight + Game.RinkTop)) { if (TrySubstitute(hock)) { SubstSignal = false; } else { StayOn(self, GetSubstitutePoint(hock).First, null); } } else { var c1 = new Point(RinkCenter.X, Game.RinkTop + 2 * HoRadius); var c2 = new Point(RinkCenter.X, Game.RinkBottom - 2 * HoRadius); var c = c1.GetDistanceTo(puck) > c2.GetDistanceTo(puck) ? c1 : c2; var s = GetStrikePoint(); StayOn(self, c, s); } } } } if (Eq(move.SpeedUp, Inf)) { move.SpeedUp = 1; } } Log(self.TeammateIndex + " >>>>>>>>>>>> " + TimerStop()); if (move.Action != ActionType.None) { Log(move.Action); } #if DEBUG draw(); Thread.Sleep(8); #endif drawInfo.Clear(); needPassQueue.Clear(); }
APuck GetStrikePuck(AHock striker, double strikePower, Point goalie, Point puckPos) { var strikerDirection = new Point(striker.Angle); var speedAngleStriker = striker.Speed.GetAngle(); var puckSpeed = 20.0 * strikePower + striker.Speed.Length * Math.Cos(striker.Angle - speedAngleStriker); var puckSpeedDirection = strikerDirection * puckSpeed; return new APuck(puckPos ?? striker.PuckPos(), puckSpeedDirection, goalie); }
public int GetTicksToDown(AHock ho, Point to, double takePuck = -1, int limit = 300) { return(GetTicksToDownN(ho.Clone(), to, takePuck, limit)); }
double ProbabStrikeAfter(int swingTime, Hockeyist self, IEnumerable<MoveAction> actions, ActionType actionType) { var I = new AHock(self); if (Math.Abs(My.NetFront - I.X) < RinkWidth / 3) return 0.0; var power = GetPower(I, swingTime); var totalTime = 0; var opps = Hockeyists .Where(x => !x.IsTeammate && IsInGame(x)) .Select(x => new AHock(x)) .ToArray(); var goalie = Get(OppGoalie); foreach (var action in actions) { for (var i = 0; i < action.Ticks; i++) { GoalieMove(goalie, 1, I.PuckPos()); I.Move(action.SpeedUp, action.Turn); if (!Chase(opps, I)) return 0.0; } totalTime += action.Ticks; } var passAngle = PassAngleNorm(I.GetAngleTo(GetStrikePoint())); return StrikeProbability(I, power, goalie, totalTime, actionType, passAngle, null); }
bool NeedTrySubstitute(AHock hock) { if (!IsFinal()) return false; var maxStamina = Hockeyists .Where(x => x.State == HockeyistState.Resting && x.IsTeammate) .Select(x => x.Stamina) .Max(); var to = Hockeyists.FirstOrDefault(x => Eq(x.Stamina, maxStamina)); if (to == null || maxStamina*0.8 < hock.Stamina) return false; return true; }
public int MoveHockTo(AHock ho, Point to) { var result = 0; for(; !CanStrike(ho, to); result++) { ho.MoveTo(to); if (result > 500) return result; } return result; }
public Tuple <Point, int, int> GoToPuck(Hockeyist my, APuck pk, int ticksLimit = 300, bool tryDown = true) { if (my.Id == puck.OwnerHockeyistId) { return(new Tuple <Point, int, int>(null, 0, 0)); } if (ticksLimit == -1) { ticksLimit = 300; } const int noBs = 100; var res = Inf; var dir = 1; var owner = Hockeyists.FirstOrDefault(x => x.Id == puck.OwnerHockeyistId); var ho = owner == null ? null : new AHock(owner); if (pk == null) { pk = new APuck(puck, OppGoalie); } else { ho = null; } var result = new Point(pk); int tLeft = 0, tRight = ticksLimit; var pks = new APuck[tRight + 1]; var hhs = new AHock[tRight + 1]; pks[0] = pk.Clone(); hhs[0] = ho; for (var i = 1; i <= tRight; i++) { pks[i] = pks[i - 1].Clone(); hhs[i] = ho == null ? null : hhs[i - 1].Clone(); PuckMove(1, pks[i], hhs[i]); } while (ticksLimit > noBs && tLeft <= tRight) { var c = (tLeft + tRight) / 2; var needTicks = GetTicksTo(PuckMove(0, pks[c], hhs[c]), my, tryDown); if (Math.Abs(needTicks) < c) { tRight = c - 1; res = c; result = PuckMove(0, pks[c], hhs[c]); dir = needTicks >= 0 ? 1 : -1; } else { tLeft = c + 1; } } const int by = 10; for (var c = 0; c <= noBs && c <= ticksLimit; c += c < by ? 1 : by) { var needTicks = GetTicksTo(PuckMove(0, pks[c], hhs[c]), my, tryDown); if (Math.Abs(needTicks) <= c) { for (var i = 0; i < by; i++, c--) { if (Math.Abs(needTicks) <= c) { res = c; result = PuckMove(0, pks[c], hhs[c]); dir = needTicks >= 0 ? 1 : -1; } } break; } } return(new Tuple <Point, int, int>(result, dir, res)); }
bool Strike(AHock striker, double strikePower, Point goalie, ActionType actionType, double passAngle, Point puckPos) { var pk = actionType == ActionType.Strike ? GetStrikePuck(striker, strikePower, goalie, puckPos) : GetPassPuck(striker, 1, passAngle, goalie); return PuckPrimitiveValidate(pk) && pk.Move(300, true) == 1; }
public bool TryStrikeWithoutTake(AHock _hock, APuck _pk) { if (!StrikePrimitiveValidate(_hock)) return false; TimerStart(); var moveDirBase = MyRight() && _hock.Y > RinkCenter.Y || MyLeft() && _hock.Y < RinkCenter.Y ? 1 : -1; var bestTurn = 0.0; var bestSpUp = 0.0; var bestProbab = 0.0; var bestWait = Inf; var swTime = 0; var range = TurnRange(_hock.AAgility); const int turns = 9; const int spUps = 8; for (var moveDir = -1; moveDir <= 1; moveDir += 2) { for (var moveTurn = 0.0; moveTurn <= range + Eps; moveTurn += range/turns) { var turn = moveDir*moveTurn; for (var spUp = 0.0; spUp <= 1.0; spUp += 1.0/spUps) { var hock = _hock.Clone(); var pk = _pk.Clone(); var ticksWait = 0; for (var startDist2 = hock.GetDistanceTo2(pk); !CanStrike(hock, pk) && ticksWait < 150; ticksWait++) { if (moveDir == moveDirBase || IsFinal() && moveTurn < range / 2) { var I = hock.Clone(); var p = pk.Clone(); for (var sw = 0; sw <= Game.MaxEffectiveSwingTicks; sw++) { if (sw >= Game.SwingActionCooldownTicks && CanStrike(I, p)) { var pr = StrikeProbability(I, GetPower(I, sw), p.Goalie, -1, ActionType.Strike, 0, p); if (pr > bestProbab) { bestProbab = pr; bestTurn = turn; bestSpUp = spUp; bestWait = ticksWait; swTime = sw; } } I.Move(0, 0); p.Move(1); } } hock.Move(spUp, turn); pk.Move(1); var dist2 = hock.GetDistanceTo2(pk); if (dist2 > startDist2) break; startDist2 = dist2; } if (CanStrike(hock, pk)) { var p = StrikeProbability(hock, GetPower(hock, 0), pk.Goalie, -1, ActionType.Strike, 0, pk); if (p > bestProbab) { bestProbab = p; bestTurn = turn; bestSpUp = spUp; bestWait = ticksWait; swTime = 0; } } } } } Log("SWING " + TimerStop()); if (bestWait == Inf) return false; move.Turn = bestTurn; move.SpeedUp = bestSpUp; if (bestWait == 0) move.Action = swTime == 0 ? ActionType.Strike : ActionType.Swing; return true; }