fix: bots continuesly trying to reach goal, after falling down while going on path.

add: bots path type (fast,optimal,safe) is now updated randomly on every round start.
add: more sse functions for mathlib, support for neon (thanks to sse2neon lib)
This commit is contained in:
dmitry 2021-09-14 15:10:14 +03:00
commit d17c1808aa
No known key found for this signature in database
GPG key ID: 8297CE728B7A7E37
10 changed files with 67 additions and 53 deletions

View file

@ -1246,17 +1246,7 @@ int Bot::pickBestWeapon (int *vec, int count, int moneySave) {
bool needMoreRandomWeapon = (m_personality == Personality::Careful) || (rg.chance (25) && m_personality == Personality::Normal);
if (needMoreRandomWeapon) {
auto pick = [] (const float factor) -> float {
union {
unsigned int u;
float f;
} cast {};
cast.f = factor;
return (static_cast <int> ((cast.u >> 23) & 0xff) - 127) * 0.3010299956639812f;
};
float buyFactor = (m_moneyAmount - static_cast <float> (moneySave)) / (16000.0f - static_cast <float> (moneySave)) * 3.0f;
auto buyFactor = (m_moneyAmount - static_cast <float> (moneySave)) / (16000.0f - static_cast <float> (moneySave)) * 3.0f;
if (buyFactor < 1.0f) {
buyFactor = 1.0f;
@ -1266,7 +1256,7 @@ int Bot::pickBestWeapon (int *vec, int count, int moneySave) {
for (int *begin = vec, *end = vec + count - 1; begin < end; ++begin, --end) {
cr::swap (*end, *begin);
}
return vec[static_cast <int> (static_cast <float> (count - 1) * pick (rg.get (1.0f, cr::powf (10.0f, buyFactor))) / buyFactor + 0.5f)];
return vec[static_cast <int> (static_cast <float> (count - 1) * cr::log10 (rg.get (1.0f, cr::powf (10.0f, buyFactor))) / buyFactor + 0.5f)];
}
int chance = 95;
@ -3242,13 +3232,13 @@ void Bot::normal_ () {
ignoreCollision ();
// did we already decide about a goal before?
auto destIndex = graph.exists (getTask ()->data) ? getTask ()->data : findBestGoal ();
auto currIndex = getTask ()->data;
auto destIndex = graph.exists (currIndex) && !isBannedNode (currIndex) ? currIndex : findBestGoal ();
// check for existance (this is failover, for i.e. csdm, this should be not true with normal gameplay, only when spawned outside of waypointed area)
if (!graph.exists (destIndex)) {
destIndex = graph.getFarest (pev->origin, 512.0f);
}
m_prevGoalIndex = destIndex;
// remember index
@ -3258,7 +3248,7 @@ void Bot::normal_ () {
// override with fast path
if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted ()) {
pathSearchType = FindPath::Fast;
pathSearchType = rg.chance (60) ? FindPath::Fast : FindPath::Optimal;
}
// do pathfinding if it's not the current waypoint
@ -4640,7 +4630,7 @@ void Bot::pickupItem_ () {
}
}
void Bot::executeTasks () {
void Bot::tasks () {
// this is core function that handle task execution
auto func = getTask ()->func;
@ -4796,7 +4786,7 @@ void Bot::logic () {
avoidGrenades (); // avoid flyings grenades
m_isUsingGrenade = false;
executeTasks (); // execute current task
tasks (); // execute current task
updateAimDir (); // choose aim direction
updateLookAngles (); // and turn to chosen aim direction

View file

@ -1565,7 +1565,7 @@ bool BotControl::executeCommands () {
if (prefix != product.cmdPri && prefix != product.cmdSec) {
return false;
}
Client &client = util.getClient (game.indexOfPlayer (m_ent));
auto &client = util.getClient (game.indexOfPlayer (m_ent));
// do not allow to execute stuff for non admins
if (m_ent != game.getLocalEntity () && !(client.flags & ClientFlags::Admin)) {

View file

@ -1217,20 +1217,7 @@ void Bot::newRound () {
m_team = game.getTeam (ent ());
m_isVIP = false;
switch (m_personality) {
default:
case Personality::Normal:
m_pathType = rg.chance (50) ? FindPath::Optimal : FindPath::Safe;
break;
case Personality::Rusher:
m_pathType = FindPath::Fast;
break;
case Personality::Careful:
m_pathType = FindPath::Safe;
break;
}
resetPathSearchType ();
// clear all states & tasks
m_states = 0;
@ -1390,6 +1377,7 @@ void Bot::newRound () {
msg = BotMsg::None;
}
m_msgQueue.clear ();
m_goalHistory.clear ();
// clear last trace
for (auto i = 0; i < TraceChannel::Num; ++i) {
@ -1410,6 +1398,23 @@ void Bot::newRound () {
m_updateInterval = game.is (GameFlags::Legacy | GameFlags::Xash3D) ? 0.0f : (1.0f / cr::clamp (cv_think_fps.float_ (), 30.0f, 60.0f));
}
void Bot::resetPathSearchType () {
switch (m_personality) {
default:
case Personality::Normal:
m_pathType = rg.chance (50) ? FindPath::Optimal : FindPath::Safe;
break;
case Personality::Rusher:
m_pathType = rg.chance (75) ? FindPath::Fast : FindPath::Optimal;
break;
case Personality::Careful:
m_pathType = rg.chance (75) ? FindPath::Safe : FindPath::Optimal;
break;
}
}
void Bot::kill () {
// this function kills a bot (not just using ClientKill, but like the CSBot does)
// base code courtesy of Lazy (from bots-united forums!)

View file

@ -12,6 +12,11 @@ ConVar cv_debug_heuristic_type ("yb_debug_heuristic_type", "0", "Selects the heu
int Bot::findBestGoal () {
auto pushToHistroy = [&] (int32 goal) -> int32 {
m_goalHistory.push (goal);
return goal;
};
// chooses a destination (goal) node for a bot
if (!bots.isBombPlanted () && m_team == Team::Terrorist && game.mapIs (MapFlags::Demolition)) {
int result = kInvalidNodeIndex;
@ -116,7 +121,7 @@ int Bot::findBestGoal () {
else if (game.mapIs (MapFlags::Demolition) && m_team == Team::Terrorist && bots.getRoundStartTime () + 10.0f < game.time ()) {
// send some terrorists to guard planted bomb
if (!m_defendedBomb && bots.isBombPlanted () && getCurrentTaskId () != Task::EscapeFromBomb && getBombTimeleft () >= 15.0) {
return m_chosenGoalIndex = graph.getNearest (graph.getBombOrigin ());
return pushToHistroy (m_chosenGoalIndex = graph.getNearest (graph.getBombOrigin ()));
}
}
@ -145,7 +150,7 @@ int Bot::findBestGoal () {
if (goalDesire > tacticChoice) {
tactic = 3;
}
return findGoalPost (tactic, defensiveNodes, offensiveNodes);
return pushToHistroy (findGoalPost (tactic, defensiveNodes, offensiveNodes));
}
int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) {
@ -234,16 +239,16 @@ void Bot::postprocessGoals (const IntArray &goals, int result[]) {
int searchCount = 0;
for (int index = 0; index < 4; ++index) {
int rand = goals.random ();
auto goal = goals.random ();
if (searchCount <= 8 && (m_prevGoalIndex == rand || ((result[0] == rand || result[1] == rand || result[2] == rand || result[3] == rand) && goals.length () > 4)) && !isOccupiedNode (rand)) {
if (searchCount <= 8 && (isBannedNode (goal) || m_prevGoalIndex == goal || ((result[0] == goal || result[1] == goal || result[2] == goal || result[3] == goal) && goals.length () > 4)) && !isOccupiedNode (goal)) {
if (index > 0) {
index--;
}
++searchCount;
continue;
}
result[index] = rand;
result[index] = goal;
}
}
@ -1562,7 +1567,7 @@ bool Bot::findBestNearestNode () {
}
// ignore non-reacheable nodes...
if (!isReachableNode (at)) {
if (!isReachableNode (at) || isBannedNode (at)) {
continue;
}
@ -1623,6 +1628,7 @@ bool Bot::findBestNearestNode () {
if (selected == kInvalidNodeIndex) {
selected = findNearestNode ();
}
m_goalHistory.push (selected);
changePointIndex (selected);
return true;
@ -3104,3 +3110,12 @@ bool Bot::isReachableNode (int index) {
}
return false;
}
bool Bot::isBannedNode (int index) {
for (const auto &node : m_goalHistory) {
if (node == index) {
return true;
}
}
return false;
}