group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
Bot Class Reference

#include <Bot.hpp>

Collaboration diagram for Bot:
[legend]

Public Member Functions

 Bot ()=default
 Bot (const Bot &)=delete
Botoperator= (const Bot &)=delete
 Bot (Bot &&)=delete
Botoperator= (Bot &&)=delete
 ~Bot ()
bool init (const std::string &host, Uint16 port, int botId)
 Connect to the server.
void setSimulatedLatencyMs (int totalMs)
 Apply a simulated round-trip latency on the bot's UDP path.
void setSimulatedLossPercent (int percent)
 Apply a simulated UDP packet-loss percentage to the bot's UDP path.
void start (const std::atomic< bool > &stopFlag)
 Spawn the worker thread.
void join ()
 Block until the worker thread exits.
float getCurrentRttMs () const
 PR-1 (server-perf): current smoothed RTT in ms.
bool isReady () const
 PR-1: true once the bot's worker has logged at least one finished tick.

Static Public Attributes

static constexpr int k_tickHz = 128
 Default tick rate; matches the server's physics tick rate.

Private Member Functions

void runLoop (const std::atomic< bool > &stopFlag)
 Worker-thread main loop: send input + poll, sleep to next tick.
void setupLocalPlayerCallback ()
 PR-23: set up the onLocalPlayerReady callback that emplaces LocalPlayer + InputSnapshot + PreviousPosition + PlayerSimState on the bot's local entity, mirroring Game::onLocalPlayerReady.
void openShotsLog ()
 Open the shot-intent log if GROUP2_BOT_SHOTS_CSV_PREFIX is set.
void writeShotIntent (std::uint16_t shooterClientId, std::uint32_t shotInputTick, const glm::vec3 &origin, const glm::vec3 &direction, std::uint16_t intendedTargetClientId, const glm::vec3 &intendedTargetPos, float intendedTargetDist, bool botRayHit, std::uint16_t botHitClientId, const glm::vec3 &botHitPos, float botHitDist)
 Append a shot-intent row.
void closeShotsLog () noexcept
 Flush + close the shot log if open. Safe from dtor.
void openObservationLog ()
 Open the CSV if GROUP2_BOT_OBS_CSV_PREFIX is set.
void writeObservationLog ()
 Walk the registry for view<Position, ClientId>, write one row per replicated player entity to the bot's CSV.
void closeObservationLog () noexcept
 Flush + close the CSV if open. Safe to call from dtor.

Private Attributes

Client client_
 Underlying TCP client (TCP today; UDP after Phase 3).
Registry registry_
 Snapshot apply target — never read.
std::thread thread_
 Worker thread; joined in dtor or join().
InputSnapshot input_ {}
 Reused per-tick input scratch.
uint32_t predictTick_ = 0
 Monotonic tick counter, stamped onto each input.
int botId_ = 0
 Log prefix.
bool initialized_ = false
 True once init() succeeded; gates run().
std::atomic< bool > ready_ {false}
 PR-1 (server-perf): set true after the first successful poll inside runLoop.
InputRingBuffer inputRing_
bool localPlayerReady_ = false
 Set true once localPlayerReadyFn fires for this bot.
std::FILE * obsCsv_ = nullptr
std::FILE * shotsCsv_ = nullptr
bool prevShootingForLog_ = false
 Rising-edge detector for fire log.

Constructor & Destructor Documentation

◆ Bot() [1/3]

Bot::Bot ( )
default
Here is the caller graph for this function:

◆ Bot() [2/3]

Bot::Bot ( const Bot & )
delete
Here is the call graph for this function:

◆ Bot() [3/3]

Bot::Bot ( Bot && )
delete
Here is the call graph for this function:

◆ ~Bot()

Bot::~Bot ( )
Here is the call graph for this function:

Member Function Documentation

◆ closeObservationLog()

void Bot::closeObservationLog ( )
privatenoexcept

Flush + close the CSV if open. Safe to call from dtor.

Here is the caller graph for this function:

◆ closeShotsLog()

void Bot::closeShotsLog ( )
privatenoexcept

Flush + close the shot log if open. Safe from dtor.

Here is the caller graph for this function:

◆ getCurrentRttMs()

float Bot::getCurrentRttMs ( ) const
nodiscard

PR-1 (server-perf): current smoothed RTT in ms.

Returns the bot's Client::getNetStats().avgRttMs snapshot so the multi-bot fleet aggregator can compute fleet-wide p50/p99 without each bot needing to log on its own cadence. Thread-safe: reads an atomic float behind the scenes; the per-bot worker thread is the sole writer.

◆ init()

bool Bot::init ( const std::string & host,
Uint16 port,
int botId )

Connect to the server.

Must succeed before run() is called.

Parameters
hostHostname or IP.
portTCP port.
botIdNumeric identifier used only for log prefix.
Returns
False on connection failure.
Here is the call graph for this function:

◆ isReady()

bool Bot::isReady ( ) const
inlinenodiscard

PR-1: true once the bot's worker has logged at least one finished tick.

Used by the aggregator to avoid showing "0 ms RTT" for bots still in the connect window.

◆ join()

void Bot::join ( )

Block until the worker thread exits.

Caller is responsible for setting the stopFlag observed by start().

◆ openObservationLog()

void Bot::openObservationLog ( )
private

Open the CSV if GROUP2_BOT_OBS_CSV_PREFIX is set.

No-op if env unset or file open fails (graceful: load tests stay fast).

Here is the caller graph for this function:

◆ openShotsLog()

void Bot::openShotsLog ( )
private

Open the shot-intent log if GROUP2_BOT_SHOTS_CSV_PREFIX is set.

No-op when env var is missing.

Here is the caller graph for this function:

◆ operator=() [1/2]

Bot & Bot::operator= ( Bot && )
delete
Here is the call graph for this function:

◆ operator=() [2/2]

Bot & Bot::operator= ( const Bot & )
delete
Here is the call graph for this function:

◆ runLoop()

void Bot::runLoop ( const std::atomic< bool > & stopFlag)
private

Worker-thread main loop: send input + poll, sleep to next tick.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setSimulatedLatencyMs()

void Bot::setSimulatedLatencyMs ( int totalMs)

Apply a simulated round-trip latency on the bot's UDP path.

Wraps Client::setSimulatedLatencyMs so the latency simulator is exercised under bot-only load tests (the real client UI's slider is the other entry point).

Parameters
totalMsTotal RTT (0–200) split half-and-half across outbound and inbound packet queues.

◆ setSimulatedLossPercent()

void Bot::setSimulatedLossPercent ( int percent)

Apply a simulated UDP packet-loss percentage to the bot's UDP path.

Wraps Client::setSimulatedLossPercent.

Parameters
percentPer-datagram drop probability (0–100).

◆ setupLocalPlayerCallback()

void Bot::setupLocalPlayerCallback ( )
private

PR-23: set up the onLocalPlayerReady callback that emplaces LocalPlayer + InputSnapshot + PreviousPosition + PlayerSimState on the bot's local entity, mirroring Game::onLocalPlayerReady.

Called from init() BEFORE client_.init() so the callback is wired before the first snapshot lands.

Here is the caller graph for this function:

◆ start()

void Bot::start ( const std::atomic< bool > & stopFlag)

Spawn the worker thread.

Returns immediately.

Parameters
stopFlagShared shutdown signal. Loop exits when set true.
Here is the call graph for this function:

◆ writeObservationLog()

void Bot::writeObservationLog ( )
private

Walk the registry for view<Position, ClientId>, write one row per replicated player entity to the bot's CSV.

Caller must have already verified Client::consumeSnapshotApplied() so we emit at snapshot rate, not tick rate.

Here is the caller graph for this function:

◆ writeShotIntent()

void Bot::writeShotIntent ( std::uint16_t shooterClientId,
std::uint32_t shotInputTick,
const glm::vec3 & origin,
const glm::vec3 & direction,
std::uint16_t intendedTargetClientId,
const glm::vec3 & intendedTargetPos,
float intendedTargetDist,
bool botRayHit,
std::uint16_t botHitClientId,
const glm::vec3 & botHitPos,
float botHitDist )
private

Append a shot-intent row.

Called from runLoop on the rising edge of input_.shooting. No-op when the log isn't open. intendedTargetEntity == entt::null means the bot fired without aiming at any visible target (random fire).

PR-22: also records the bot's local AABB raycast result — "who the bot would think it hit" with the limited information it has on its side. Bots have no replicated HitboxInstance (capsule-level skeleton), so this is necessarily AABB-only; the server still does full capsule lag-comp. Mismatches between bot-side and server-side hits are the headline hit-reg signal the netsync analyzer reports.

Here is the caller graph for this function:

Member Data Documentation

◆ botId_

int Bot::botId_ = 0
private

Log prefix.

◆ client_

Client Bot::client_
private

Underlying TCP client (TCP today; UDP after Phase 3).

◆ initialized_

bool Bot::initialized_ = false
private

True once init() succeeded; gates run().

◆ input_

InputSnapshot Bot::input_ {}
private

Reused per-tick input scratch.

◆ inputRing_

InputRingBuffer Bot::inputRing_
private

◆ k_tickHz

int Bot::k_tickHz = 128
staticconstexpr

Default tick rate; matches the server's physics tick rate.

◆ localPlayerReady_

bool Bot::localPlayerReady_ = false
private

Set true once localPlayerReadyFn fires for this bot.

Gates the prediction loop so we don't try to runPrediction before the bot has its LocalPlayer / InputSnapshot / PlayerSimState components in the registry.

◆ obsCsv_

std::FILE* Bot::obsCsv_ = nullptr
private

◆ predictTick_

uint32_t Bot::predictTick_ = 0
private

Monotonic tick counter, stamped onto each input.

◆ prevShootingForLog_

bool Bot::prevShootingForLog_ = false
private

Rising-edge detector for fire log.

◆ ready_

std::atomic<bool> Bot::ready_ {false}
private

PR-1 (server-perf): set true after the first successful poll inside runLoop.

Lets the fleet aggregator skip bots that are mid-connect or whose RTT hasn't been measured yet.

◆ registry_

Registry Bot::registry_
private

Snapshot apply target — never read.

◆ shotsCsv_

std::FILE* Bot::shotsCsv_ = nullptr
private

◆ thread_

std::thread Bot::thread_
private

Worker thread; joined in dtor or join().


The documentation for this class was generated from the following files: