backport: nodes flooder (analyzer) from cs-ebot

analyze: allow to disable goal marking
analyze: add cvars descriptions and bounds
nav: added optional post path smoothing for astar algorithm
nav: now bots will use Dijkstra algo instead of floyd-warshall if memory usage too high (controlled via yb_path_floyd_memory_limit cvar) (fixes #434)
nav: vistable are now calculated every frame to prevent game-freeze during loading the game (fixes #434)
graph: pracrice reworked to hash table so memory footprint is as low as possible (at cost 5-10% performance loss on practice) (fixes #434)
control: bots commands now is case-insensitive
bot: major refactoring of bot's code
nav: issue warnings about path fail only with debug
practice: check for visibility when updating danger index
analyzer: suspend any analyzing on change level
control: add kickall_ct/kickall_t
nav: increase blocked distance in stuck check
This commit is contained in:
jeefo 2023-05-02 09:42:43 +03:00 committed by GitHub
commit e7712a551a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 3114 additions and 1722 deletions

View file

@ -7,6 +7,9 @@
#pragma once
constexpr int kMaxNodes = 4096; // max nodes per graph
constexpr int kMaxNodeLinks = 8; // max links for single node
// defines for nodes flags field (32 bits are available)
CR_DECLARE_SCOPED_ENUM (NodeFlag,
Lift = cr::bit (1), // wait for lift to be down before approaching this node
@ -43,13 +46,6 @@ CR_DECLARE_SCOPED_ENUM (PathConnection,
Bidirectional
)
// a* route state
CR_DECLARE_SCOPED_ENUM (RouteState,
Open = 0,
Closed,
New
)
// node edit states
CR_DECLARE_SCOPED_ENUM (GraphEdit,
On = cr::bit (1),
@ -57,26 +53,6 @@ CR_DECLARE_SCOPED_ENUM (GraphEdit,
Auto = cr::bit (3)
)
// storage header options
CR_DECLARE_SCOPED_ENUM (StorageOption,
Practice = cr::bit (0), // this is practice (experience) file
Matrix = cr::bit (1), // this is floyd warshal path & distance matrix
Vistable = cr::bit (2), // this is vistable data
Graph = cr::bit (3), // this is a node graph data
Official = cr::bit (4), // this is additional flag for graph indicates graph are official
Recovered = cr::bit (5), // this is additional flag indicates graph converted from podbot and was bad
Exten = cr::bit (6) // this is additional flag indicates that there's extension info
)
// storage header versions
CR_DECLARE_SCOPED_ENUM (StorageVersion,
Graph = 2,
Practice = 1,
Vistable = 2,
Matrix = 1,
Podbot = 7
)
// lift usage states
CR_DECLARE_SCOPED_ENUM (LiftState,
None = 0,
@ -103,29 +79,13 @@ CR_DECLARE_SCOPED_ENUM (NodeAddFlag,
Goal = 100
)
// a* route
struct Route {
float g, f;
int parent;
RouteState state;
};
CR_DECLARE_SCOPED_ENUM (NotifySound,
Done = 0,
Change = 1,
Added = 2
)
// general stprage header information structure
struct StorageHeader {
int32_t magic;
int32_t version;
int32_t options;
int32_t length;
int32_t compressed;
int32_t uncompressed;
};
// extension header for graph information
struct ExtenHeader {
char author[32]; // original author of graph
int32_t mapSize; // bsp size for checksumming map consistency
char modified[32]; // by whom modified
};
#include <vistable.h>
// general waypoint header information structure
struct PODGraphHeader {
@ -136,19 +96,6 @@ struct PODGraphHeader {
char author[32];
};
// floyd-warshall matrices
struct Matrix {
int16_t dist;
int16_t index;
};
// experience data hold in memory while playing
struct Practice {
int16_t damage[kGameTeamNum];
int16_t index[kGameTeamNum];
int16_t value[kGameTeamNum];
};
// defines linked waypoints
struct PathLink {
Vector velocity;
@ -157,11 +104,6 @@ struct PathLink {
int16_t index;
};
// defines visibility count
struct PathVis {
uint16_t stand, crouch;
};
// define graph path structure for yapb
struct Path {
int32_t number, flags;
@ -183,74 +125,21 @@ struct PODPath {
PathVis vis;
};
// this structure links nodes returned from pathfinder
class PathWalk final : public DenyCopying {
private:
size_t m_cursor {};
size_t m_length {};
// general stprage header information structure
struct StorageHeader {
int32_t magic;
int32_t version;
int32_t options;
int32_t length;
int32_t compressed;
int32_t uncompressed;
};
UniquePtr <int32_t[]> m_path {};
public:
explicit PathWalk () = default;
~PathWalk () = default;
public:
int32_t &next () {
return at (1);
}
int32_t &first () {
return at (0);
}
int32_t &last () {
return at (length () - 1);
}
int32_t &at (size_t index) {
return m_path[m_cursor + index];
}
void shift () {
++m_cursor;
}
void reverse () {
for (size_t i = 0; i < m_length / 2; ++i) {
cr::swap (m_path[i], m_path[m_length - 1 - i]);
}
}
size_t length () const {
if (m_cursor >= m_length) {
return 0;
}
return m_length - m_cursor;
}
bool hasNext () const {
return length () > m_cursor;
}
bool empty () const {
return !length ();
}
void add (int32_t node) {
m_path[m_length++] = node;
}
void clear () {
m_cursor = 0;
m_length = 0;
m_path[0] = 0;
}
void init (size_t length) {
m_path = cr::makeUnique <int32_t []> (length);
}
// extension header for graph information
struct ExtenHeader {
char author[32]; // original author of graph
int32_t mapSize; // bsp size for checksumming map consistency
char modified[32]; // by whom modified
};
// graph operation class
@ -260,7 +149,6 @@ public:
private:
int m_editFlags {};
int m_loadAttempts {};
int m_cacheNodeIndex {};
int m_lastJumpNode {};
int m_findWPIndex {};
@ -277,8 +165,8 @@ private:
bool m_endJumpPoint {};
bool m_jumpLearnNode {};
bool m_hasChanged {};
bool m_needsVisRebuild {};
bool m_narrowChecked {};
bool m_silenceMessages {};
Vector m_learnVelocity {};
Vector m_learnPosition {};
@ -293,11 +181,8 @@ private:
IntArray m_rescuePoints {};
IntArray m_visitedGoals {};
SmallArray <Matrix> m_matrix {};
SmallArray <Practice> m_practice {};
public:
SmallArray <Path> m_paths {};
SmallArray <uint8_t> m_vistable {};
HashMap <int32_t, Array <int32_t>, EmptyHash <int32_t>> m_hashTable;
String m_graphAuthor {};
@ -315,13 +200,10 @@ public:
public:
int getFacingIndex ();
int getFarest (const Vector &origin, float maxDistance = 32.0);
int getForAnalyzer (const Vector &origin, float maxDistance);
int getNearest (const Vector &origin, float minDistance = kInfiniteDistance, int flags = -1);
int getNearestNoBuckets (const Vector &origin, float minDistance = kInfiniteDistance, int flags = -1);
int getEditorNearest ();
int getDangerIndex (int team, int start, int goal);
int getDangerValue (int team, int start, int goal);
int getDangerDamage (int team, int start, int goal);
int getPathDist (int srcIndex, int destIndex);
int clearConnections (int index);
int getBspSize ();
int locateBucket (const Vector &pos);
@ -329,30 +211,23 @@ public:
float calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin);
bool convertOldFormat ();
bool isVisible (int srcIndex, int destIndex);
bool isStandVisible (int srcIndex, int destIndex);
bool isDuckVisible (int srcIndex, int destIndex);
bool isConnected (int a, int b);
bool isConnected (int index);
bool isNodeReacheableEx (const Vector &src, const Vector &destination, const float maxHeight);
bool isNodeReacheable (const Vector &src, const Vector &destination);
bool isNodeReacheableWithJump (const Vector &src, const Vector &destination);
bool checkNodes (bool teleportPlayer);
bool loadPathMatrix ();
bool isVisited (int index);
bool isAnalyzed () const;
bool saveGraphData ();
bool loadGraphData ();
bool canDownload ();
template <typename U> bool saveStorage (StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten);
template <typename U> bool loadStorage (StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions);
template <typename ...Args> bool raiseLoadingError (bool isGraph, bool isDebug, MemFile &file, const char *fmt, Args &&...args);
void saveOldFormat ();
void reset ();
void frame ();
void loadPractice ();
void loadVisibility ();
void initNodesTypes ();
void populateNodes ();
void initLightLevels ();
void initNarrowPlaces ();
void addPath (int addIndex, int pathIndex, float distance);
@ -360,16 +235,11 @@ public:
void erase (int target);
void toggleFlags (int toggleFlag);
void setRadius (int index, float radius);
void rebuildVisibility ();
void pathCreate (char dir);
void erasePath ();
void cachePoint (int index);
void calculatePathRadius (int index);
void savePractice ();
void saveVisibility ();
void addBasic ();
void eraseFromDisk ();
void savePathMatrix ();
void setSearchIndex (int index);
void startLearnJump ();
void setVisited (int index);
@ -378,16 +248,14 @@ public:
void addToBucket (const Vector &pos, int index);
void eraseFromBucket (const Vector &pos, int index);
void setBombOrigin (bool reset = false, const Vector &pos = nullptr);
void updateGlobalPractice ();
void unassignPath (int from, int to);
void setDangerValue (int team, int start, int goal, int value);
void setDangerDamage (int team, int start, int goal, int value);
void convertFromPOD (Path &path, const PODPath &pod);
void convertToPOD (const Path &path, PODPath &pod);
void convertCampDirection (Path &path);
void setAutoPathDistance (const float distance);
void showStats ();
void showFileInfo ();
void emitNotify (int32_t sound);
IntArray getNarestInRadius (float radius, const Vector &origin, int maxCount = -1);
const IntArray &getNodesInBucket (const Vector &pos);
@ -463,6 +331,25 @@ public:
return m_editor;
}
// slicence all graph messages or not
void setMessageSilence (bool enable) {
m_silenceMessages = enable;
}
// set exten header from binary storage
void setExtenHeader (ExtenHeader *hdr) {
memcpy (&m_extenHeader, hdr, sizeof (ExtenHeader));
}
// set graph header from binary storage
void setGraphHeader (StorageHeader *hdr) {
memcpy (&m_graphHeader, hdr, sizeof (StorageHeader));
}
public:
// graph heloer for sending message to correct channel
template <typename ...Args> void msg (const char *fmt, Args &&...args);
public:
Path *begin () {
return m_paths.begin ();
@ -481,29 +368,8 @@ public:
}
};
// we're need `bots`
#include <manager.h>
// helper for reporting load errors
template <typename ...Args> bool BotGraph::raiseLoadingError (bool isGraph, bool isDebug, MemFile &file, const char *fmt, Args &&...args) {
auto result = strings.format (fmt, cr::forward <Args> (args)...);
// display error only for graph file
if (isGraph || isDebug) {
logger.error (result);
}
// if graph reset paths
if (isGraph) {
bots.kickEveryone (true);
m_graphAuthor = result;
m_paths.clear ();
}
file.close ();
return false;
}
#include <practice.h>
// explose global
CR_EXPOSE_GLOBAL_SINGLETON (BotGraph, graph);