Skip to content

Commit 192607b

Browse files
committed
Add hivemind batch input
1 parent 12dd65d commit 192607b

File tree

13 files changed

+346
-203
lines changed

13 files changed

+346
-203
lines changed

ExampleBot/ExampleBot.cpp

Lines changed: 90 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <cstdio>
99
#include <cstdlib>
1010
#include <numbers>
11+
#include <unordered_set>
1112
using namespace std::chrono_literals;
1213

1314
namespace
@@ -47,91 +48,107 @@ float angleSteer (T const angle_) noexcept
4748
///////////////////////////////////////////////////////////////////////////
4849
ExampleBot::~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

137154
void 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 ());

ExampleBot/ExampleBot.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <rlbot/Bot.h>
44

55
#include <chrono>
6+
#include <string>
7+
#include <unordered_set>
68

79
class ExampleBot final : public rlbot::Bot
810
{
@@ -11,7 +13,7 @@ class ExampleBot final : public rlbot::Bot
1113

1214
ExampleBot () noexcept = delete;
1315

14-
ExampleBot (int index_, int team_, std::string name_) noexcept;
16+
ExampleBot (std::unordered_set<unsigned> indices_, unsigned team_, std::string name_) noexcept;
1517

1618
ExampleBot (ExampleBot const &) noexcept = delete;
1719

@@ -21,11 +23,13 @@ class ExampleBot final : public rlbot::Bot
2123

2224
ExampleBot &operator= (ExampleBot &&) noexcept = delete;
2325

24-
rlbot::flat::ControllerState getOutput (rlbot::flat::GamePacket const *packet_,
26+
void update (rlbot::flat::GamePacket const *packet_,
2527
rlbot::flat::BallPrediction const *ballPrediction_,
2628
rlbot::flat::FieldInfo const *fieldInfo_,
2729
rlbot::flat::MatchSettings const *matchSettings_) noexcept override;
2830

31+
rlbot::flat::ControllerState getOutput (unsigned index_) noexcept override;
32+
2933
void matchComm (rlbot::flat::MatchComm const *matchComm_) noexcept override;
3034

3135
private:

ExampleBot/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ int main (int argc_, char *argv_[])
4242
auto const host = argc_ > 1 ? argv_[1] : "127.0.0.1";
4343
auto const port = argc_ > 2 ? argv_[2] : serverPort;
4444

45-
rlbot::BotManager<ExampleBot> manager;
45+
rlbot::BotManager<ExampleBot> manager{true};
4646
if (!manager.run (host, port, agentId, true))
4747
{
4848
std::fprintf (stderr, "Usage: %s [addr] [port]\n", argv_[0]);

benchmark/Simulator.cpp

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ Simulator::Simulator (Private) noexcept
213213
{
214214
m_ballPrediction.slices.resize (6 * 120);
215215

216+
constexpr auto NUM_CARS = 2;
217+
for (unsigned i = 0; i < NUM_CARS; ++i)
216218
{
217219
auto &player =
218220
m_gamePacket.players.emplace_back (std::make_unique<rlbot::flat::PlayerInfoT> ());
@@ -295,14 +297,17 @@ bool Simulator::run () noexcept
295297

296298
m_delays.clear ();
297299

298-
m_car = m_arena->AddCar (RocketSim::Team::BLUE);
299-
m_arena->ResetToRandomKickoff ();
300+
for (auto &player : m_gamePacket.players)
301+
{
302+
auto const car = m_cars.emplace_back (m_arena->AddCar (RocketSim::Team::BLUE));
300303

301-
m_gamePacket.players[0]->hitbox->length = m_car->config.hitboxSize.x;
302-
m_gamePacket.players[0]->hitbox->width = m_car->config.hitboxSize.y;
303-
m_gamePacket.players[0]->hitbox->height = m_car->config.hitboxSize.z;
304+
player->hitbox->length = car->config.hitboxSize.x;
305+
player->hitbox->width = car->config.hitboxSize.y;
306+
player->hitbox->height = car->config.hitboxSize.z;
307+
*player->hitbox_offset = fromRocketSim (car->config.hitboxPosOffset);
308+
}
304309

305-
*m_gamePacket.players[0]->hitbox_offset = fromRocketSim (m_car->config.hitboxPosOffset);
310+
m_arena->ResetToRandomKickoff ();
306311

307312
constexpr auto tps = 120;
308313

@@ -336,8 +341,8 @@ bool Simulator::run () noexcept
336341
if (!sendGamePacket ())
337342
return false;
338343

339-
bool input = false;
340-
while (!input)
344+
unsigned inputs = 0;
345+
while (inputs < m_gamePacket.players.size ())
341346
{
342347
auto message = readMessage ();
343348
if (!message)
@@ -348,7 +353,7 @@ bool Simulator::run () noexcept
348353
case MessageType::PlayerInput:
349354
if (!handlePlayerInput (std::move (message)))
350355
return false;
351-
input = true;
356+
++inputs;
352357
break;
353358

354359
default:
@@ -431,12 +436,14 @@ bool Simulator::sendMatchSettings () noexcept
431436
matchSettings.enable_rendering = true;
432437
matchSettings.enable_state_setting = true;
433438

439+
for (unsigned i = 0; i < m_gamePacket.players.size (); ++i)
434440
{
435441
auto &playerConfig = matchSettings.player_configurations.emplace_back (
436442
std::make_unique<rlbot::flat::PlayerConfigurationT> ());
437443

438444
playerConfig->variety.Set (rlbot::flat::RLBotT{});
439445
playerConfig->agent_id = m_agendId;
446+
playerConfig->spawn_id = i;
440447
}
441448

442449
matchSettings.mutator_settings = std::make_unique<rlbot::flat::MutatorSettingsT> ();
@@ -456,10 +463,13 @@ bool Simulator::sendControllableTeamInfo () noexcept
456463
rlbot::flat::ControllableTeamInfoT controllableTeamInfo;
457464
controllableTeamInfo.team = 0;
458465

459-
auto &player = controllableTeamInfo.controllables.emplace_back (
460-
std::make_unique<rlbot::flat::ControllableInfoT> ());
461-
player->index = 0;
462-
player->spawn_id = 0;
466+
for (unsigned i = 0; i < m_gamePacket.players.size (); ++i)
467+
{
468+
auto &controllable = controllableTeamInfo.controllables.emplace_back (
469+
std::make_unique<rlbot::flat::ControllableInfoT> ());
470+
controllable->index = i;
471+
controllable->spawn_id = i;
472+
}
463473

464474
auto fbb = m_fbbPool->getObject ();
465475
fbb->Finish (rlbot::flat::CreateControllableTeamInfo (*fbb, &controllableTeamInfo));
@@ -497,13 +507,16 @@ bool Simulator::sendBallPrediction () noexcept
497507

498508
bool Simulator::sendGamePacket () noexcept
499509
{
500-
*m_gamePacket.players[0]->physics =
501-
rlbot::flat::Physics (fromRocketSim (m_car->GetState ().pos),
502-
fromRocketSim (m_car->GetState ().rotMat),
503-
fromRocketSim (m_car->GetState ().vel),
504-
fromRocketSim (m_car->GetState ().angVel));
510+
for (unsigned i = 0; auto &player : m_gamePacket.players)
511+
{
512+
auto const car = m_cars[i++];
513+
*player->physics = rlbot::flat::Physics (fromRocketSim (car->GetState ().pos),
514+
fromRocketSim (car->GetState ().rotMat),
515+
fromRocketSim (car->GetState ().vel),
516+
fromRocketSim (car->GetState ().angVel));
505517

506-
m_gamePacket.players[0]->boost = m_car->GetState ().boost;
518+
player->boost = car->GetState ().boost;
519+
}
507520

508521
auto fbb = m_fbbPool->getObject ();
509522
fbb->Finish (rlbot::flat::CreateGamePacket (*fbb, &m_gamePacket));
@@ -530,16 +543,21 @@ bool Simulator::handlePlayerInput (Message message_) noexcept
530543
if (!state)
531544
return false;
532545

533-
*m_gamePacket.players[0]->last_input = *state;
546+
if (input->player_index () >= std::min (m_cars.size (), m_gamePacket.players.size ()))
547+
return false;
548+
549+
auto const car = m_cars[input->player_index ()];
550+
551+
*m_gamePacket.players[input->player_index ()]->last_input = *state;
534552

535-
m_car->controls.throttle = state->throttle ();
536-
m_car->controls.steer = state->steer ();
537-
m_car->controls.pitch = state->pitch ();
538-
m_car->controls.yaw = state->yaw ();
539-
m_car->controls.roll = state->roll ();
540-
m_car->controls.jump = state->jump ();
541-
m_car->controls.boost = state->boost ();
542-
m_car->controls.handbrake = state->handbrake ();
553+
car->controls.throttle = state->throttle ();
554+
car->controls.steer = state->steer ();
555+
car->controls.pitch = state->pitch ();
556+
car->controls.yaw = state->yaw ();
557+
car->controls.roll = state->roll ();
558+
car->controls.jump = state->jump ();
559+
car->controls.boost = state->boost ();
560+
car->controls.handbrake = state->handbrake ();
543561

544562
auto const sendTime = m_outTimestamps[static_cast<unsigned> (MessageType::GamePacket)];
545563
auto const recvTime = m_inTimestamps[static_cast<unsigned> (MessageType::PlayerInput)];

benchmark/Simulator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Simulator
5454

5555
std::unique_ptr<RocketSim::Arena> m_arena;
5656
std::unique_ptr<RocketSim::BallPredTracker> m_ballPredTracker;
57-
RocketSim::Car *m_car = nullptr;
57+
std::vector<RocketSim::Car *> m_cars;
5858

5959
SOCKET m_sock = INVALID_SOCKET;
6060

0 commit comments

Comments
 (0)