88#include < cstdio>
99#include < cstdlib>
1010#include < numbers>
11+ #include < unordered_set>
1112using namespace std ::chrono_literals;
1213
1314namespace
@@ -47,91 +48,107 @@ float angleSteer (T const angle_) noexcept
4748// /////////////////////////////////////////////////////////////////////////
4849ExampleBot::~ExampleBot () noexcept = default ;
4950
50- ExampleBot::ExampleBot (int const index_, int const team_, std::string name_) noexcept
51- : rlbot::Bot (index_, team_, std::move (name_))
51+ ExampleBot::ExampleBot (std::unordered_set<unsigned > indices_,
52+ unsigned const team_,
53+ std::string name_) noexcept
54+ : rlbot::Bot (std::move (indices_), team_, std::move (name_))
5255{
53- std::printf (" Team %u Index %u: Example Bot created\n " , team_, index_);
56+ std::set<unsigned > sorted (std::begin (indices), std::end (indices));
57+ for (auto const &index : sorted)
58+ std::printf (" Team %u Index %u: Example Bot created\n " , team_, index);
5459}
5560
56- rlbot::flat::ControllerState ExampleBot::getOutput (rlbot::flat::GamePacket const *const packet_,
61+ void ExampleBot::update (rlbot::flat::GamePacket const *const packet_,
5762 rlbot::flat::BallPrediction const *const ballPrediction_,
5863 rlbot::flat::FieldInfo const *const fieldInfo_,
5964 rlbot::flat::MatchSettings const *const matchSettings_) noexcept
6065{
6166 auto const now = std::chrono::steady_clock::now ();
62- if (!m_comms && now - m_start > 5s)
63- {
64- // demonstrate sending of a match comm
65- sendMatchComm (" Here is a team message" , {}, true );
66- m_comms = true ;
67- }
68- else if (!m_rendered && now - m_start > 10s)
69- {
70- rlbot::flat::CarAnchorT carAnchor;
71- carAnchor.index = index;
72- carAnchor.local = std::make_unique<rlbot::flat::Vector3> ();
73-
74- rlbot::flat::BallAnchorT ballAnchor;
75- ballAnchor.index = 0 ;
76- ballAnchor.local = std::make_unique<rlbot::flat::Vector3> ();
77-
78- rlbot::flat::Line3DT line;
7967
80- line.start = std::make_unique<rlbot::flat::RenderAnchorT> ();
81- line.start ->world = std::make_unique<rlbot::flat::Vector3> ();
82- line.start ->relative .Set (std::move (carAnchor));
68+ auto const prevComms = m_comms;
69+ auto const prevRendered = m_rendered;
8370
84- line.end = std::make_unique<rlbot::flat::RenderAnchorT> ();
85- line.end ->world = std::make_unique<rlbot::flat::Vector3> ();
86- line.end ->relative .Set (std::move (ballAnchor));
87-
88- line.color = std::make_unique<rlbot::flat::Color> (255 , 255 , 255 , 255 );
89-
90- rlbot::flat::RenderMessageT render;
91- render.variety .Set (line);
92-
93- // demonstrate sending of a render message
94- // group id is unique to a connection (one per team with hivemind, one per bot without)
95- sendRenderMessage (index + 100 , std::move (render));
96- sendMatchComm (" Enabled render" , {}, true );
97- m_rendered = true ;
98- }
99- else if (!m_stateSet && now - m_start > 15s)
71+ for (auto const &index : this ->indices )
10072 {
101- auto ballState = std::make_unique<rlbot::flat::DesiredBallStateT> ();
102- ballState->physics = std::make_unique<rlbot::flat::DesiredPhysicsT> ();
103-
104- ballState->physics ->location = std::make_unique<rlbot::flat::Vector3PartialT> ();
105- ballState->physics ->location ->x = std::make_unique<rlbot::flat::Float> (0 .0f );
106- ballState->physics ->location ->y = std::make_unique<rlbot::flat::Float> (0 .0f );
107- ballState->physics ->location ->z = std::make_unique<rlbot::flat::Float> (0 .0f );
108-
109- rlbot::flat::DesiredGameStateT state;
110- state.ball_states .emplace_back (std::move (ballState));
111-
112- // demonstrate sending of desired game state
113- sendDesiredGameState (state);
114- sendMatchComm (" State set" , {}, true );
115- m_stateSet = true ;
73+ if (!prevComms && now - m_start > 5s)
74+ {
75+ // demonstrate sending of a match comm
76+ sendMatchComm (index, " Here is a team message" , {}, true );
77+ m_comms = true ;
78+ }
79+ else if (!prevRendered && now - m_start > 10s)
80+ {
81+ rlbot::flat::CarAnchorT carAnchor;
82+ carAnchor.index = index;
83+ carAnchor.local = std::make_unique<rlbot::flat::Vector3> ();
84+
85+ rlbot::flat::BallAnchorT ballAnchor;
86+ ballAnchor.index = 0 ;
87+ ballAnchor.local = std::make_unique<rlbot::flat::Vector3> ();
88+
89+ rlbot::flat::Line3DT line;
90+
91+ line.start = std::make_unique<rlbot::flat::RenderAnchorT> ();
92+ line.start ->world = std::make_unique<rlbot::flat::Vector3> ();
93+ line.start ->relative .Set (std::move (carAnchor));
94+
95+ line.end = std::make_unique<rlbot::flat::RenderAnchorT> ();
96+ line.end ->world = std::make_unique<rlbot::flat::Vector3> ();
97+ line.end ->relative .Set (std::move (ballAnchor));
98+
99+ line.color = std::make_unique<rlbot::flat::Color> (255 , 255 , 255 , 255 );
100+
101+ rlbot::flat::RenderMessageT render;
102+ render.variety .Set (line);
103+
104+ // demonstrate sending of a render message
105+ // group id is unique to a connection (one per team with hivemind, one per bot without)
106+ sendRenderMessage (index + 100 , std::move (render));
107+ sendMatchComm (index, " Enabled render" , {}, true );
108+ m_rendered = true ;
109+ }
110+ else if (!m_stateSet && now - m_start > 15s)
111+ {
112+ auto ballState = std::make_unique<rlbot::flat::DesiredBallStateT> ();
113+ ballState->physics = std::make_unique<rlbot::flat::DesiredPhysicsT> ();
114+
115+ ballState->physics ->location = std::make_unique<rlbot::flat::Vector3PartialT> ();
116+ ballState->physics ->location ->x = std::make_unique<rlbot::flat::Float> (0 .0f );
117+ ballState->physics ->location ->y = std::make_unique<rlbot::flat::Float> (0 .0f );
118+ ballState->physics ->location ->z = std::make_unique<rlbot::flat::Float> (0 .0f );
119+
120+ rlbot::flat::DesiredGameStateT state;
121+ state.ball_states .emplace_back (std::move (ballState));
122+
123+ // demonstrate sending of desired game state
124+ sendDesiredGameState (state);
125+ sendMatchComm (index, " State set" , {}, true );
126+ m_stateSet = true ;
127+ }
128+
129+ auto const balls = packet_->balls ();
130+ auto const players = packet_->players ();
131+ if (balls->size () == 0 || players->size () <= index)
132+ continue ;
133+
134+ auto const ballPos = balls->Get (0 )->physics ()->location ();
135+ auto const carPos = players->Get (index)->physics ()->location ();
136+ auto const carRot = players->Get (index)->physics ()->rotation ();
137+
138+ auto const dx = ballPos.x () - carPos.x ();
139+ auto const dy = ballPos.y () - carPos.y ();
140+ auto const angle = std::atan2 (dy, dx);
141+
142+ auto const steer = angleSteer (angle - carRot.yaw ());
143+ auto const handbrake = std::abs (steer) >= 1 .0f ;
144+
145+ outputs[index] = {1 .0f , steer, 0 .0f , 0 .0f , 0 .0f , false , false , handbrake, false };
116146 }
147+ }
117148
118- auto const balls = packet_->balls ();
119- auto const players = packet_->players ();
120- if (balls->size () == 0 || players->size () <= index)
121- return {};
122-
123- auto const ballPos = balls->Get (0 )->physics ()->location ();
124- auto const carPos = players->Get (index)->physics ()->location ();
125- auto const carRot = players->Get (index)->physics ()->rotation ();
126-
127- auto const dx = ballPos.x () - carPos.x ();
128- auto const dy = ballPos.y () - carPos.y ();
129- auto const angle = std::atan2 (dy, dx);
130-
131- auto const steer = angleSteer (angle - carRot.yaw ());
132- auto const handbrake = std::abs (steer) >= 1 .0f ;
133-
134- return {1 .0f , steer, 0 .0f , 0 .0f , 0 .0f , false , false , handbrake, false };
149+ rlbot::flat::ControllerState ExampleBot::getOutput (unsigned const index_) noexcept
150+ {
151+ return outputs[index_];
135152}
136153
137154void ExampleBot::matchComm (rlbot::flat::MatchComm const *const matchComm_) noexcept
@@ -140,7 +157,7 @@ void ExampleBot::matchComm (rlbot::flat::MatchComm const *const matchComm_) noex
140157 if (display->size () != 0 )
141158 std::printf (" To [%d:%d] From [%d:%d]: %s\n " ,
142159 team,
143- index ,
160+ std::ranges::min (indices) ,
144161 matchComm_->team (),
145162 matchComm_->index (),
146163 display->c_str ());
0 commit comments