/// <summary> /// Calls the given bot's <see cref="Bot.GetOutput(GameTickPacket)"/> method and /// updates its input through the interface DLL. /// </summary> /// <param name="bot"></param> private void RunBot(Bot bot) { while (true) { try { GameTickPacket gameTickPacket = RLBotInterface.GetGameTickPacket(); Controller botInput = bot.GetOutput(gameTickPacket); RLBotInterface.SetBotInput(botInput, bot.index); } catch (FlatbuffersPacketException) { // Ignore if the packet size is too small. No need to warn the user. } catch (Exception e) { // Don't crash the bot and give the user the details of the exception instead. Console.WriteLine(e.GetType()); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } botRunEvent.WaitOne(); } }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); // // Wrap gameTickPacket retrieving in a try-catch so that the bot doesn't crash whenever a value isn't present. // // A value may not be present if it was not sent. // // These are nullables so trying to get them when they're null will cause errors, therefore we wrap in try-catch. // try // { // // Store the required data from the gameTickPacket. // var ball = gameTickPacket.Ball.Value; // var myCar = gameTickPacket.Players(index).Value; // controller.Steer = BallChasingService.GetSteeringValueToChaseBall(myCar, ball); // } // catch (Exception e) // { // System.Console.WriteLine(e.Message); // System.Console.WriteLine(e.StackTrace); // } // // Set the throttle to 1 so the bot can move. // controller.Throttle = 1; return(controller); }
private static float SetPitchTarget(GameTickPacket gameTickPacket, int index, double x, double y, double z = 0) { Vector3 carLocation = gameTickPacket.Players(index).Value.Physics.Value.Location.Value; Rotator carRotation = gameTickPacket.Players(index).Value.Physics.Value.Rotation.Value; var carToGroundAngle = Math.Atan2(0 - carLocation.Z, 0 - carRotation.Pitch); carToGroundAngle = CorrectAngle(carToGroundAngle); var botFrontToTargetAngle = carLocation.Z - z; //Console.WriteLine(carRotation.Pitch); if (botFrontToTargetAngle == 0) { return(0); } if (botFrontToTargetAngle > 0 && carRotation.Pitch > 0) { return(-0.1f); } if (botFrontToTargetAngle < 0 && carRotation.Pitch < 0.5) { return(0.5f); } return(0); }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); // Wrap gameTickPacket retrieving in a try-catch so that the bot doesn't crash whenever a value isn't present. // A value may not be present if it was not sent. // These are nullables so trying to get them when they're null will cause errors, therefore we wrap in try-catch. try { // Store the required data from the gameTickPacket. Vector3 ballLocation = gameTickPacket.Ball.Value.Physics.Value.Location.Value; Vector3 carLocation = gameTickPacket.Players(this.index).Value.Physics.Value.Location.Value; Rotator carRotation = gameTickPacket.Players(this.index).Value.Physics.Value.Rotation.Value; // Calculate to get the angle from the front of the bot's car to the ball. double botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); double botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; // Correct the angle if (botFrontToTargetAngle < -Math.PI) { botFrontToTargetAngle += 2 * Math.PI; } if (botFrontToTargetAngle > Math.PI) { botFrontToTargetAngle -= 2 * Math.PI; } // Decide which way to steer in order to get to the ball. if (botFrontToTargetAngle > 0) { controller.Steer = 1; } else { controller.Steer = -1; } Renderer.DrawLine3D(Color.FromRgb(255, 255, 0), new System.Numerics.Vector3(ballLocation.X, ballLocation.Y, ballLocation.Z), new System.Numerics.Vector3(carLocation.X, carLocation.Y, carLocation.Z)); // controller.Steer = 0; } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } // Set the throttle to 1 so the bot can move. controller.Throttle = 1; return(controller); }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); // Wrap gameTickPacket retrieving in a try-catch so that the bot doesn't crash whenever a value isn't present. // A value may not be present if it was not sent. // These are nullables so trying to get them when they're null will cause errors, therefore we wrap in try-catch. try { // Store the required data from the gameTickPacket. Vector3 ballLocation = gameTickPacket.Ball.Value.Physics.Value.Location.Value; Vector3 botLocation = gameTickPacket.Players(this.index).Value.Physics.Value.Location.Value; Rotator botRotation = gameTickPacket.Players(this.index).Value.Physics.Value.Rotation.Value; double botDistanceToBall = GetDistanceToTarget(ballLocation, botLocation); double botToBallAngle = GetAngleToBall(ballLocation, botLocation); double botFrontToBallAngle = botToBallAngle - botRotation.Yaw; double botToGoalAngle = Math.Atan2(_opponentGoalLocation.Y - botLocation.Y, _opponentGoalLocation.X - botLocation.X); double botFrontToGoalAngle = botToGoalAngle - botRotation.Yaw; // Correct the angle if (botFrontToGoalAngle < -Math.PI) { botFrontToGoalAngle += 2 * Math.PI; } if (botFrontToGoalAngle > Math.PI) { botFrontToGoalAngle -= 2 * Math.PI; } // Decide which way to steer in order to get to the ball. if (botFrontToGoalAngle > 0) { controller.Steer = 1; } else { controller.Steer = -1; } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } // Set the throttle to 1 so the bot can move. controller.Throttle = 1; return(controller); }
/// <summary> /// Returns the current frame's GameTickPacket. /// </summary> /// <returns>The current frame's GameTickPacket.</returns> public static GameTickPacket GetGameTickPacket() { ByteBufferStruct byteBuffer = UpdateLiveDataPacketFlatbuffer(); if (byteBuffer.size < 4) throw new FlatbuffersPacketException("Flatbuffers packet is too small. Match is probably not running!"); byte[] bufferBytes = new byte[byteBuffer.size]; Marshal.Copy(byteBuffer.ptr, bufferBytes, 0, byteBuffer.size); return GameTickPacket.GetRootAsGameTickPacket(new ByteBuffer(bufferBytes)); }
protected override void Update(GameTickPacket gameTickPacket) { if (Action != BotAction.Default) { PerformAction(gameTickPacket); } else { PerformStateActions(gameTickPacket); } }
protected void SetDesiredState(GameTickPacket gameTickPacket) { if (DesiredState != null) { State = DesiredState.Value; DesiredState = null; return; } if (State != BotState.Kickoff) { if (ShouldChangeToKickoff()) { SendQuickChatFromAgent(false, QuickChatSelection.Information_IGotIt); State = BotState.Kickoff; return; } if (ShouldChangeToChasing() && State != BotState.Chasing) { SendQuickChatFromAgent(false, QuickChatSelection.Information_IGotIt); TurnAroud(); State = BotState.Chasing; } else if (ShouldChangeToDefending() && State != BotState.Defending) { SendQuickChatFromAgent(false, QuickChatSelection.Information_Defending); State = BotState.Defending; return; } else if (ShouldChangeToWaitingForCenter() && State != BotState.WaitingForCenter) { SendQuickChatFromAgent(false, QuickChatSelection.Information_InPosition); var enemyGoalZone = Field.Zones.First(z => z.IsMySide == false && z.HasGoal); var targetZoneId = enemyGoalZone.Id > 6 ? enemyGoalZone.Id - 3 : enemyGoalZone.Id + 3; TargetZone = Field.Zones.First(z => z.Id == targetZoneId); TurnTarget = TargetZone.Rec.Center(); TurnAroud(); State = BotState.Chasing; } } else { if (Ball.Location != null && (Ball.Location.X != 0 || Ball.Location.Y != 0)) { SendQuickChatFromAgent(false, QuickChatSelection.Information_IGotIt); State = BotState.Chasing; } } }
public static GameTickPacket WaitForFreshPacket(int timeoutMillis, int key) { ByteBufferStruct byteBuffer = FreshLiveDataPacketFlatbuffer(timeoutMillis, key); if (byteBuffer.size < 4) { throw new FlatbuffersPacketException("Flatbuffers packet is too small. Match is probably not running!"); } byte[] bufferBytes = new byte[byteBuffer.size]; Marshal.Copy(byteBuffer.ptr, bufferBytes, 0, byteBuffer.size); Free(byteBuffer.ptr); return(GameTickPacket.GetRootAsGameTickPacket(new ByteBuffer(bufferBytes))); }
private void PerformAction(GameTickPacket gameTickPacket) { switch (Action) { case BotAction.Flipping: FlipAction(); break; case BotAction.TurningAround: TurnAroud(); break; case BotAction.Aerial: Aerial(); break; } }
private Controller GoForKickoff(GameTickPacket gameTickPacket, Controller controller) { target = Target.Ball; controller.Boost = true; controller.Steer = SetSteerTarget(gameTickPacket, index, 0, 0); if (controller.Steer > 0.2) { controller.Steer = 0.2f; } if (controller.Steer < -0.2) { controller.Steer = -0.2f; } controller.Throttle = 1; return(controller); }
/// <summary> /// Gets called every game tick. Returns a controller state /// </summary> /// <param name="gameTickPacket"></param> /// <returns>The desired controller inputs to be pressed</returns> public override Controller GetOutput(GameTickPacket gameTickPacket) { try { GameState gameState = GameState.ParseFromPacket(gameTickPacket); Ball ball = Ball.ParseFromGamePacket(gameTickPacket); BotState botState = BotState.ParseFromGameState(gameState, index); Destination destination = Destination.DecideDestination(map, gameState, botState, allyTeam, enemyTeam); controller = CarControl.GetControllerForDestination(controller, destination, botState); controller.Throttle = 1f; Debug.DrawAll(Renderer, botState, car, ball, map, allyTeam, enemyTeam); } catch (Exception ex) { Console.WriteLine(ex); } return(controller); }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); _gameDataMgr.PreProcess(gameTickPacket); // Store the required data from the gameTickPacket. // The GameTickPacket's attributes are nullables, so you must use .Value. // It is recommended to create your own internal data structure to avoid the displeasing .Value syntax. Vector3 ballLocation = gameTickPacket.Ball.Value.Physics.Value.Location.Value; Vector3 carLocation = gameTickPacket.Players(this.index).Value.Physics.Value.Location.Value; Rotator carRotation = gameTickPacket.Players(this.index).Value.Physics.Value.Rotation.Value; // Calculate to get the angle from the front of the bot's car to the ball. double botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); double botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; // Correct the angle if (botFrontToTargetAngle < -Math.PI) { botFrontToTargetAngle += 2 * Math.PI; } if (botFrontToTargetAngle > Math.PI) { botFrontToTargetAngle -= 2 * Math.PI; } // Decide which way to steer in order to get to the ball. if (botFrontToTargetAngle > 0) { controller.Steer = 1; } else { controller.Steer = -1; } // Set the throttle to 1 so the bot can move. controller.Throttle = 1; return(controller); }
/// <summary> /// Creates a GameState from a GameTickPacket. Usefull for saving a scenario. /// </summary> /// <param name="gameTickPacket">The packet to create the GameState from.</param> /// <returns></returns> public static GameState CreateFromGameTickPacket(GameTickPacket gameTickPacket) { GameState gameState = new GameState(); if (gameTickPacket.Ball.HasValue) { gameState.BallState = new BallState(gameTickPacket.Ball.Value); } for (int i = 0; i < gameTickPacket.PlayersLength; i++) { if (gameTickPacket.Players(i).HasValue) { gameState.SetCarState(i, new CarState(gameTickPacket.Players(i).Value)); } } return(gameState); }
public override Controller GetOutput(GameTickPacket gameTickPacket) { try { //Set Reused Values Ball.UpdateInfo(gameTickPacket.Ball); Info.UpdateInfo(gameTickPacket.Players(this.index).Value); Game.UpdateInfo(gameTickPacket.GameInfo.Value); //Perform Bot Updates Update(gameTickPacket); } catch (Exception e) { System.Console.WriteLine(e.Message); System.Console.WriteLine(e.StackTrace); } return(Controller); }
/// <summary> /// Calls the given bot's <see cref="Bot.GetOutput(GameTickPacket)"/> method and /// updates its input through the interface DLL. /// </summary> private void RunBot(Bot bot, AutoResetEvent botRunEvent) { BotLoopRenderer renderer = GetRendererForBot(bot); bot.Renderer = renderer; Console.WriteLine("Waiting for the RLBot Interface to initialize..."); while (!RLBotInterface.IsInitialized()) { Thread.Sleep(100); } Console.WriteLine("The RLBot Interface has been successfully initialized!"); Console.WriteLine("Running the bot loop..."); while (true) { try { renderer.StartPacket(); GameTickPacket gameTickPacket = RLBotInterface.GetGameTickPacket(); Controller botInput = bot.GetOutput(gameTickPacket); RLBotInterface.SetBotInput(botInput, bot.index); renderer.FinishAndSendIfDifferent(); } catch (FlatbuffersPacketException) { // Ignore if the packet size is too small. No need to warn the user. } catch (Exception e) { // Don't crash the bot and give the user the details of the exception instead. Console.WriteLine(e.GetType()); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } botRunEvent.WaitOne(); } }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); // Wrap gameTickPacket retrieving in a try-catch so that the bot doesn't crash whenever a value isn't present. // A value may not be present if it was not sent. // These are nullables so trying to get them when they're null will cause errors, therefore we wrap in try-catch. try { // Store the required data from the gameTickPacket. Vector3 ballLocation = gameTickPacket.Ball.Value.Physics.Value.Location.Value; Vector3 carLocation = gameTickPacket.Players(this.index).Value.Physics.Value.Location.Value; Rotator carRotation = gameTickPacket.Players(this.index).Value.Physics.Value.Rotation.Value; // Calculate to get the angle from the front of the bot's car to the ball. double botToTargetAngle = GetHorizontalAngle(carLocation, ballLocation); double botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; // Correct the angle botFrontToTargetAngle = CorrectAngle(botFrontToTargetAngle); // Decide which way to steer in order to get to the ball. controller.Steer = (float)(botFrontToTargetAngle / Math.PI); /* Throttle between 0.5 and 1 depending on the steering angle * 0 Steer = 1 Throttle * +-1 Steer = 0.5 Throttle * A simply y = -2x+1 equation */ controller.Throttle = (float)(-2 * Math.Abs(controller.Steer)) + 1; } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } return(controller); }
private static float SetSteerTarget(GameTickPacket gameTickPacket, int index, double x, double y, double z = 0) { Vector3 carLocation = gameTickPacket.Players(index).Value.Physics.Value.Location.Value; Rotator carRotation = gameTickPacket.Players(index).Value.Physics.Value.Rotation.Value; var botToTargetAngle = Math.Atan2(y - carLocation.Y, x - carLocation.X); double botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; botFrontToTargetAngle = CorrectAngle(botFrontToTargetAngle); if (botFrontToTargetAngle == 0) { return(0); } if (botFrontToTargetAngle > 0 && botFrontToTargetAngle < DegreesToRadians(45)) { return(smallSteering); } if (botFrontToTargetAngle > 0 && botFrontToTargetAngle < DegreesToRadians(90)) { return(medSteering); } if (botFrontToTargetAngle > 0 && botFrontToTargetAngle > DegreesToRadians(90)) { return(largeSteering); } if (botFrontToTargetAngle < 0 && Math.Abs(botFrontToTargetAngle) < DegreesToRadians(45)) { return(-smallSteering); } if (botFrontToTargetAngle < 0 && Math.Abs(botFrontToTargetAngle) < DegreesToRadians(90)) { return(-medSteering); } if (botFrontToTargetAngle < 0 && Math.Abs(botFrontToTargetAngle) > DegreesToRadians(90)) { return(-largeSteering); } return(0); }
public static void Update(this WorldState worldState, GameTickPacket partial) { if (partial.Ball.HasValue) { worldState.Ball.Update(partial.Ball.Value); } for (int i = 0, l = partial.PlayersLength; i < l; i++) { var partialPlayer = partial.Players(i); if (partialPlayer.HasValue) { var player = worldState.Players.FirstOrDefault(p => p.Index == i); if (player == null) { player = new Player(partialPlayer.Value.Name, partialPlayer.Value.Team, i); worldState.Players.Add(player); } player.Update(partialPlayer.Value); } } for (int i = 0, l = partial.BoostPadStatesLength; i < l; i++) { var partialBoostPadState = partial.BoostPadStates(i); if (partialBoostPadState.HasValue) { var boostPad = worldState.BoostPads[i]; boostPad.IsActive = partialBoostPadState.Value.IsActive; boostPad.Timer = new TimeSpan(0, 0, (int)partialBoostPadState.Value.Timer); } } if (partial.GameInfo.HasValue) { worldState.Update(partial.GameInfo.Value); } }
private void PerformStateActions(GameTickPacket gameTickPacket) { switch (State) { case BotState.Kickoff: PerformKickoff(); break; case BotState.Chasing: DribbleBallAtGoal(); CheckForShot(); break; case BotState.Defending: GoToGoal(); break; case BotState.WaitingForCenter: WaitForCenter(); break; } SetDesiredState(gameTickPacket); }
protected virtual void Update(GameTickPacket gameTickPacket) { }
public void PreProcess(GameTickPacket gameTickPacket) { }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); // Wrap gameTickPacket retrieving in a try-catch so that the bot doesn't crash whenever a value isn't present. // A value may not be present if it was not sent. // These are nullables so trying to get them when they're null will cause errors, therefore we wrap in try-catch. try { if (gameInfo == null) { gameInfo = new KipjeBot.GameInfo(index, team, name); SetTeammates(); } if (fieldInfo == null) { fieldInfo = new KipjeBot.GameTickPacket.FieldInfo(GetFieldInfo()); } if (ballPrediction == null) { ballPrediction = new BallPredictionCollection(); } gameInfo.Update(gameTickPacket, GetRigidBodyTick()); ballPrediction.Update(GetBallPrediction()); Car car = gameInfo.Cars[index]; Ball ball = gameInfo.Ball; PlayerInfo playerInfo = gameTickPacket.Players(this.index).Value; if (playerInfo.Name == "BrokenJoey") { controller.Throttle = 1; controller.Steer = -0.3f; controller.Boost = true; return(controller); } target = Target.Undecided; // Store the required data from the gameTickPacket. BallInfo ballInfo = gameTickPacket.Ball.Value; Vector3 ballLocation = ballInfo.Physics.Value.Location.Value; Vector3 carLocation = playerInfo.Physics.Value.Location.Value; Rotator carRotation = playerInfo.Physics.Value.Rotation.Value; Vector3 ballVelocity = ballInfo.Physics.Value.Velocity.Value; Vector3 carVelocityStruct = playerInfo.Physics.Value.Velocity.Value; System.Numerics.Vector3 carVelocity = new System.Numerics.Vector3(carVelocityStruct.X, carVelocityStruct.Y, carVelocityStruct.Z); var velocityValue = Math.Sqrt(carVelocity.LengthSquared()); int ownGoalY = team == 0 ? -5000 : 5000; int oppGoalY = team == 0 ? 5000 : -5000; // Calculate to get the angle from the front of the bot's car to the target. //If car is in front of ball aim for goal, else aim for ball var ballTrajectoryX = ballLocation.X; var ballTrajectoryY = ballLocation.Y; var ballTrajectoryZ = ballLocation.Z; double botToTargetAngle = 0; double botToBallAngle; double botToOppGoalAngle; var DistanceToBall = Get2DDistance(carLocation.X, ballLocation.X, carLocation.Y, ballLocation.Y); botToBallAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); double botFrontToBallAngle = botToBallAngle - carRotation.Yaw; botFrontToBallAngle = CorrectAngle(botFrontToBallAngle); float goalY = Math.Abs(GetFieldInfo().Goals(0).Value.Location.Value.Y); if (GetFieldInfo().GoalsLength > 2) { mode = GameMode.Dropshot; } else if (goalY == 5120) { mode = GameMode.Soccar; } else { mode = GameMode.Hoops; } botToOppGoalAngle = Math.Atan2(oppGoalY - carLocation.Y, 0 - carLocation.X); double botFrontToOppGoalAngle = botToOppGoalAngle - carRotation.Yaw; botFrontToOppGoalAngle = CorrectAngle(botFrontToOppGoalAngle); int fieldLength = GetFieldLength(mode); controller.Jump = false; controller.Handbrake = false; //work out state code if (teammates == null) { SetTeammates(); } if (prevTarget == Target.Waiting && gameInfo.IsKickOffPause) { target = Target.Waiting; } else if (gameInfo.IsKickOffPause && gameInfo.IsRoundActive) { target = Target.Kickoff; } //goalkeeper mode else if (teammates.Count() >= MinTeammatesForGK && ((ownGoalY < 0 && carLocation.Y < (from x in teammates select x.Position.Y).Min()) || (ownGoalY > 0 && carLocation.Y > (from x in teammates select x.Position.Y).Max()))) { //if (target != Target.AwayFromGoal) //{ //team 0 = blue team, defending negative, attacking positive if (team == 0) { if (ballLocation.Y < GoalieBallTargetY * -1) { target = Target.Ball; botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); } else if (ballLocation.Y > 1000) { if (Math.Abs(ballLocation.X) < 800) { target = Target.Ball; botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); } else if (carLocation.Y < -1000 || Math.Abs(botFrontToBallAngle) > DegreesToRadians(30)) { target = Target.SpecificPoint; TargetPointX = 0; TargetPointY = 0; } else { target = Target.Waiting; } } else if (carLocation.Y < GoalieWaitY * -1 && Math.Abs(carLocation.X) < 700 && Math.Abs(botFrontToBallAngle) < DegreesToRadians(45)) { target = Target.Waiting; } else { target = Target.Goal; botToTargetAngle = Math.Atan2(goalY * -1 - carLocation.Y, 0 - carLocation.X); } } else //team 1 = orange team, defending positive, attacking negative { if (ballLocation.Y > GoalieBallTargetY) { target = Target.Ball; botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); } else if (ballLocation.Y < -1000) { if (Math.Abs(ballLocation.X) < 800) { target = Target.Ball; botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); } else if (carLocation.Y > 1000 || Math.Abs(botFrontToBallAngle) > DegreesToRadians(30)) { target = Target.SpecificPoint; TargetPointX = 0; TargetPointY = 0; } else { target = Target.Waiting; } } else if (carLocation.Y > GoalieWaitY && Math.Abs(carLocation.X) < 700 && Math.Abs(botFrontToBallAngle) < DegreesToRadians(45)) { target = Target.Waiting; } else { target = Target.Goal; botToTargetAngle = Math.Atan2(goalY - carLocation.Y, 0 - carLocation.X); } } //} } //car is in goal else if (GetFieldInfo().GoalsLength == 2 && ((Math.Abs(carLocation.Y) > Math.Abs(goalY) - ownGoalTurnDistance && (prevTarget == Target.Goal || prevTarget == Target.AwayFromGoal)) || carLocation.Y > Math.Abs(goalY))) { botToTargetAngle = Math.Atan2(-carLocation.Y, 0); if (Math.Abs(ballLocation.X) < 1000) { target = Target.Ball; } else { target = Target.AwayFromGoal; } } else if (ballLocation.X == 0 && ballLocation.Y == 0) { target = Target.Ball; botToTargetAngle = Math.Atan2(0 - carLocation.Y, 0 - carLocation.X); } //defending when blue else if (GetFieldInfo().GoalsLength == 2 && team == 0 && (carLocation.Y > ballLocation.Y || (prevTarget == Target.Goal && carLocation.Y > ballLocation.Y - 1000)) && ballVelocity.Y < 0) { botToTargetAngle = Math.Atan2(goalY * -1 - carLocation.Y, 0 - carLocation.X); controller.Boost = true; target = Target.Goal; } //defending when orange else if (GetFieldInfo().GoalsLength == 2 && team == 1 && (carLocation.Y < ballLocation.Y || (prevTarget == Target.Goal && carLocation.Y < ballLocation.Y + 1000)) && ballVelocity.Y > 0) { botToTargetAngle = Math.Atan2(goalY - carLocation.Y, 0 - carLocation.X); controller.Boost = true; target = Target.Goal; } else { var goForBall = true; if (teammates.Count >= MinTeammatesForWait) { var distanceToBall = car.DistanceToBall(ball); var teammateDistance = (from x in teammates select x.DistanceToBall(ball)).Min(); if (teammateDistance < distanceToBall && teammateDistance < 2000) { goForBall = false; } if (Math.Abs(ballLocation.X) < 1000 && teammateDistance > 500 && teammateDistance < 1500) { goForBall = true; } } if (goForBall) { botToTargetAngle = botToBallAngle; var trajectoryAngle = Math.Atan2(ballVelocity.Y - carVelocity.Y, ballVelocity.X - carVelocity.X); if (playerInfo.Boost > 10 && ballLocation.Z > 700 && Math.Abs(botFrontToBallAngle) < Math.Abs(DegreesToRadians(20)) && (Math.Abs(trajectoryAngle) < DegreesToRadians(maxAerialTrajectoryAngleDegrees) || Math.Abs(trajectoryAngle) > 180 - maxAerialTrajectoryAngleDegrees)) { target = Target.BallInAir; } else { if (ballLocation.Z > ballLandingPointHeight) { target = Target.BallLandingPoint; } else { target = Target.Ball; } } botToTargetAngle = botToBallAngle; } else { if (Math.Abs(carLocation.X) < 800 && Math.Abs(botFrontToOppGoalAngle) < DegreesToRadians(30)) { //if ball behind, reposition other side of ball target = Target.Waiting; //blue if (team == 0) { if (carLocation.Y > ballLocation.Y) { target = Target.SpecificPoint; TargetPointX = carLocation.X; TargetPointY = ballLocation.Y - 1000; } } //orange else { if (carLocation.Y < ballLocation.Y) { target = Target.SpecificPoint; TargetPointX = carLocation.X; TargetPointY = ballLocation.Y + 1000; } } } else { TargetPointX = 0; TargetPointY = team == 0 ? 2000 : -2000; if (team == 0 && ballLocation.Y < 2000) { TargetPointY = ballLocation.Y - 1000; } if (team == 1 && ballLocation.Y > -2000) { TargetPointY = ballLocation.Y + 1000; } target = Target.SpecificPoint; } } } double botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; // Correct the angle botFrontToTargetAngle = CorrectAngle(botFrontToTargetAngle); if (DistanceToBall <= 300 && botFrontToTargetAngle < MinimumSteeringAngleRadians / 2 && ballLocation.Z < 200 && ballLocation.X != 0 && ballLocation.Y != 0) { target = Target.GuidingBall; } if (target == Target.Ball) { Slice[] slices = ballPrediction.ToArray(); float targetTime = 0; double ballVelocityUnit = Math.Sqrt(ballVelocity.X * ballVelocity.X + ballVelocity.Y * ballVelocity.Y); if (ballVelocityUnit < 200 || DistanceToBall < 600) { targetTime = 0.1f; } else if (ballVelocityUnit < 400) { targetTime = 0.6f; } else if (ballVelocityUnit < 600) { targetTime = 1.25f; } else { targetTime = 2; } Slice?targetSlice = slices.Where(x => x.Time - gameInfo.Time >= targetTime).FirstOrDefault(); if (targetSlice != null) { target = Target.SpecificPoint; TargetPointX = targetSlice.Value.Position.X; TargetPointY = targetSlice.Value.Position.Y; } } switch (target) { case Target.BallInAir: Slice[] slices = ballPrediction.ToArray(); if (aerial == null) { for (int i = 0; i < slices.Length; i++) { float B_avg = Aerial.CalculateCourse(car, slices[i].Position, slices[i].Time - gameInfo.Time).Length(); if (B_avg < 970) { aerial = new Aerial(car, slices[i].Position, gameInfo.Time, slices[i].Time); break; } } controller.Jump = true; } else { controller = aerial.Step(ball, 0.0083335f, gameInfo.Time); controller.Boost = true; if (aerial.Finished) { aerial = null; } else { for (int i = 0; i < slices.Length; i++) { if (Math.Abs(slices[i].Time - aerial.ArrivalTime) < 0.02) { if ((aerial.Target - slices[i].Position).Length() > 40) { aerial = null; } break; } } } } break; case Target.BallLandingPoint: if (ballVelocity.X == 0 && ballVelocity.Y == 0) { controller.Throttle = 1; controller.Boost = true; } else { //speed calculation based on height of ball var slice = ballPrediction.GetNextGroundTouch(); if (slice != null) { var target = slice.Value; var distance = Math.Abs(Get2DDistance(target.Position.X, carLocation.X, target.Position.Y, carLocation.Y)) + 100; var time = target.Time - gameTickPacket.GameInfo.Value.SecondsElapsed; var ticks = time * 120; var currentDistance = ticks * velocityValue; if (currentDistance < distance) { controller.Throttle = 1; controller.Boost = true; } else { controller.Throttle = 0.1f; controller.Boost = false; } } controller = SetSteeringBasedOnTarget(controller, botFrontToTargetAngle); } break; case Target.GuidingBall: var complete = false; ballTrajectoryX = ballLocation.X; ballTrajectoryY = ballLocation.Y; while (!complete) { if (ballTrajectoryY > GetFieldLength(mode)) { if (oppGoalY == 5000 && mode == GameMode.Soccar) { if (ballLocation.X < 700 && ballLocation.X > -700) { complete = true; } else { if (ballLocation.X < -700) { controller.Steer = -largeSteering; } else { controller.Steer = largeSteering; } complete = true; } } else { controller.Steer = 1; complete = true; } } else if (ballTrajectoryY < GetFieldLength(mode) * -1) { if (oppGoalY == -5000 && mode == GameMode.Soccar) { if (ballLocation.X < 700 && ballLocation.X > -700) { complete = true; } else { if (ballLocation.X < -700) { controller.Steer = -largeSteering; } else { controller.Steer = largeSteering; } complete = true; } } else { controller.Steer = 1; complete = true; } } else if (ballTrajectoryX < -700 && ballLocation.X > -700 && mode == GameMode.Soccar) { controller.Steer = -smallSteering; complete = true; } else if (ballTrajectoryX > 700 && ballLocation.X < 700 && mode == GameMode.Soccar) { controller.Steer = smallSteering; complete = true; } if (botFrontToBallAngle > DegreesToRadians(180)) { controller.Steer *= -1; } if (ballVelocity.X == 0 && ballVelocity.Y == 0) { complete = true; } if (!complete) { ballTrajectoryX += ballVelocity.X; ballTrajectoryY += ballVelocity.Y; } } controller.Throttle = 1; break; case Target.Kickoff: if (teammates == null) { SetTeammates(); } if (teammates.Count() == 0) { controller = GoForKickoff(gameTickPacket, controller); SetJump(ref controller, ref ballLocation, ref carLocation, DistanceToBall, botFrontToBallAngle); } else { var furthestTeammate = (from x in teammates select x.DistanceToCentre()).Max(); if (gameInfo.MyCar.DistanceToCentre() <= furthestTeammate) { controller = GoForKickoff(gameTickPacket, controller); SetJump(ref controller, ref ballLocation, ref carLocation, DistanceToBall, botFrontToBallAngle); } else { target = Target.Waiting; controller.Throttle = 0; controller.Handbrake = true; controller.Steer = 0; } } break; case Target.SpecificPoint: botToTargetAngle = Math.Atan2(TargetPointY - carLocation.Y, TargetPointX - carLocation.X); botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; // Correct the angle botFrontToTargetAngle = CorrectAngle(botFrontToTargetAngle); SetHandbrakeAndBoost(ref controller, ref carLocation, carVelocity, botFrontToTargetAngle); SetJump(ref controller, ref ballLocation, ref carLocation, DistanceToBall, botFrontToBallAngle); SetThrottle(ref controller, ref ballLocation, ref carLocation, ballVelocity, DistanceToBall, botFrontToTargetAngle); controller = SetSteeringBasedOnTarget(controller, botFrontToTargetAngle); break; case Target.Waiting: controller.Throttle = 0; break; default: SetHandbrakeAndBoost(ref controller, ref carLocation, carVelocity, botFrontToTargetAngle); SetJump(ref controller, ref ballLocation, ref carLocation, DistanceToBall, botFrontToBallAngle); SetThrottle(ref controller, ref ballLocation, ref carLocation, ballVelocity, DistanceToBall, botFrontToTargetAngle); controller = SetSteeringBasedOnTarget(controller, botFrontToTargetAngle); if (target == Target.AwayFromGoal && Math.Abs(botFrontToTargetAngle) > DegreesToRadians(90)) { controller.Handbrake = true; } if (target == Target.AwayFromGoal) { controller.Boost = false; } break; } switch (target) { case Target.Ball: Renderer.DrawLine3D(System.Windows.Media.Color.FromRgb(255, 0, 0), new System.Numerics.Vector3(carLocation.X, carLocation.Y, carLocation.Z), new System.Numerics.Vector3(ballLocation.X, ballLocation.Y, ballLocation.Z)); break; case Target.BallInAir: Renderer.DrawLine3D(System.Windows.Media.Color.FromRgb(255, 255, 0), new System.Numerics.Vector3(carLocation.X, carLocation.Y, carLocation.Z), new System.Numerics.Vector3(ballLocation.X, ballLocation.Y, ballLocation.Z)); break; case Target.BallLandingPoint: Renderer.DrawLine3D(System.Windows.Media.Color.FromRgb(0, 255, 0), new System.Numerics.Vector3(carLocation.X, carLocation.Y, carLocation.Z), new System.Numerics.Vector3(ballTrajectoryX, ballTrajectoryY, ballTrajectoryZ)); break; case Target.Goal: Renderer.DrawLine3D(System.Windows.Media.Color.FromRgb(0, 0, 255), new System.Numerics.Vector3(carLocation.X, carLocation.Y, carLocation.Z), new System.Numerics.Vector3(0, ownGoalY, 10)); break; case Target.AwayFromGoal: Renderer.DrawLine3D(System.Windows.Media.Color.FromRgb(0, 0, 0), new System.Numerics.Vector3(carLocation.X, carLocation.Y, carLocation.Z), new System.Numerics.Vector3(ballLocation.X, ballLocation.Y, ballLocation.Z)); break; case Target.Undecided: Renderer.DrawLine3D(System.Windows.Media.Color.FromRgb(255, 255, 255), new System.Numerics.Vector3(carLocation.X, carLocation.Y, carLocation.Z), new System.Numerics.Vector3(ballLocation.X, ballLocation.Y, ballLocation.Z)); break; } prevTarget = target; LastPositionX = carLocation.X; LastPositionY = carLocation.Y; LastBallPositionX = ballLocation.X; LastBallPositionY = ballLocation.Y; LastBallPositionZ = ballLocation.Z; if (DateTime.Now > lastChat.AddSeconds(10) && random.NextDouble() < 0.00033) { int chatNo = (int)(random.NextDouble() * 63); try { SendQuickChatFromAgent(false, (QuickChatSelection)chatNo); } catch { Console.WriteLine("QuickChat Exception: " + chatNo); } lastChat = DateTime.Now; } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } return(controller); }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); // Wrap gameTickPacket retrieving in a try-catch so that the bot doesn't crash whenever a value isn't present. // A value may not be present if it was not sent. // These are nullables so trying to get them when they're null will cause errors, therefore we wrap in try-catch. try { // Store the required data from the gameTickPacket. Vector3 ballLocation = gameTickPacket.Ball.Value.Physics.Value.Location.Value; Vector3 carLocation = gameTickPacket.Players(this.Index).Value.Physics.Value.Location.Value; Rotator carRotation = gameTickPacket.Players(this.Index).Value.Physics.Value.Rotation.Value; // Calculate to get the angle from the front of the bot's car to the ball. double botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); double botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; // Correct the angle if (botFrontToTargetAngle < -Math.PI) { botFrontToTargetAngle += 2 * Math.PI; } if (botFrontToTargetAngle > Math.PI) { botFrontToTargetAngle -= 2 * Math.PI; } // Decide which way to steer in order to get to the ball. if (botFrontToTargetAngle > 0) { controller.Steer = 1; } else { controller.Steer = -1; } Renderer.DrawLine3D(Color.FromArgb(255, 255, 0), ballLocation, carLocation); // Get the ball prediction data. BallPrediction prediction = GetBallPrediction(); // Loop through every 10th point so we don't render too many lines. for (int i = 10; i < prediction.SlicesLength; i += 10) { Vector3 pointA = prediction.Slices(i - 10).Value.Physics.Value.Location.Value; Vector3 pointB = prediction.Slices(i).Value.Physics.Value.Location.Value; Renderer.DrawLine3D(Color.FromArgb(255, 0, 255), pointA, pointB); } // Test out setting game state GameState gameState = new GameState(); // Make the ball hover in midair gameState.BallState.PhysicsState = new PhysicsState(location: new DesiredVector3(z: 300), velocity: new DesiredVector3(z: 10)); // If the ball stops moving, fling the car at it Vector3 ballVelocity = gameTickPacket.Ball.Value.Physics.Value.Velocity.Value; if (ballVelocity.X * ballVelocity.X + ballVelocity.Y * ballVelocity.Y < 100000 && carLocation.Z < 100) { PhysicsState carPhysicsState = gameState.GetCarState(Index).PhysicsState; carPhysicsState.Location = new DesiredVector3(ballLocation.X - 300, ballLocation.Y, 400); carPhysicsState.Velocity = new DesiredVector3(500, 0, 0); if (gameTickPacket.Ball?.LatestTouch?.PlayerIndex is int playerIndex) { Console.WriteLine("Latest touch by " + playerIndex); } MatchSettings matchSettings = GetMatchSettings(); Console.WriteLine("Map: " + matchSettings.GameMap); } SetGameState(gameState); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } // Set the throttle to 1 so the bot can move. controller.Throttle = 1; controller.UseItem = controller.Steer > 0; // Spam items return(controller); }
public override Controller GetOutput(GameTickPacket gameTickPacket) { // This controller object will be returned at the end of the method. // This controller will contain all the inputs that we want the bot to perform. Controller controller = new Controller(); // Wrap gameTickPacket retrieving in a try-catch so that the bot doesn't crash whenever a value isn't present. // A value may not be present if it was not sent. // These are nullables so trying to get them when they're null will cause errors, therefore we wrap in try-catch. try { // Store the required data from the gameTickPacket. Vector3 ballLocation = gameTickPacket.Ball.Value.Physics.Value.Location.Value; Vector3 carLocation = gameTickPacket.Players(this.index).Value.Physics.Value.Location.Value; Rotator carRotation = gameTickPacket.Players(this.index).Value.Physics.Value.Rotation.Value; PlayerInfo car = gameTickPacket.Players(this.index).Value; // Calculate to get the angle from the front of the bot's car to the ball. double botToTargetAngle = Math.Atan2(ballLocation.Y - carLocation.Y, ballLocation.X - carLocation.X); double botFrontToTargetAngle = botToTargetAngle - carRotation.Yaw; // Correct the angle if (botFrontToTargetAngle < -Math.PI) { botFrontToTargetAngle += 2 * Math.PI; } if (botFrontToTargetAngle > Math.PI) { botFrontToTargetAngle -= 2 * Math.PI; } controller.Boost = false; var steerAngle = 0f; if (car.Boost == 0 && !needBoost) { // Go to a random boost pad needBoost = true; targetBoostId = rnd.Next(BoostLocations.Length - 1); Console.WriteLine($"Car {this.index}: Need Boost!"); } else if (car.Boost > 80) { // Don't need boost, go for ball needBoost = false; } if (needBoost) { // Looking for boost steerAngle = CollectBoost(targetBoostId, carLocation, carRotation); // Find new boost pad after we hit our target if (getDistanceToPoint(carLocation, BoostLocations[targetBoostId]) < 100) { targetBoostId = rnd.Next(BoostLocations.Length - 1); } // Walls tend to break things. if (carLocation.Z > 200) { targetBoostId = rnd.Next(BoostLocations.Length - 1); } } else { // Go for ball! steerAngle = botFrontToTargetAngle > 0 ? 1 : -1; } // Boost towards ball! controller.Boost = (getDistanceToBall(carLocation, ballLocation) < 2000); controller.Steer = steerAngle; } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } // Set the throttle to 1 so the bot can move. controller.Throttle = 1; return(controller); }
/// <summary> /// This method should contain the bot logic that should be executed every frame. /// </summary> /// <param name="gameTickPacket">The game data input.</param> /// <returns>Should return the Controller outputs that the bot should execute.</returns> public abstract Controller GetOutput(GameTickPacket gameTickPacket);