From f46e6d3527739979e9eaded3da7395d00f9a48cd Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Fri, 14 Feb 2014 13:04:47 +0100 Subject: [PATCH] Beginning of useless WP detection. --- qcsrc/server/bot/navigation.qc | 13 ++- qcsrc/server/bot/waypoints.qc | 164 ++++++++++++++++++++++++--------- qcsrc/server/bot/waypoints.qh | 2 + 3 files changed, 132 insertions(+), 47 deletions(-) diff --git a/qcsrc/server/bot/navigation.qc b/qcsrc/server/bot/navigation.qc index 691ce3e0a..0facbf037 100644 --- a/qcsrc/server/bot/navigation.qc +++ b/qcsrc/server/bot/navigation.qc @@ -366,7 +366,7 @@ float navigation_waypoint_will_link(vector v, vector org, entity ent, float walk } // find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon -entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, float bestdist) +entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfromwp, float bestdist, entity except) { entity waylist, w, best; vector v, org, pm1, pm2; @@ -380,7 +380,7 @@ entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, flo while (w) { // if object is touching spawnfunc_waypoint - if(w != ent) + if(w != ent && w != except) if (boxesoverlap(pm1, pm2, w.absmin, w.absmax)) return w; w = w.chain; @@ -426,7 +426,14 @@ entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, flo } entity navigation_findnearestwaypoint(entity ent, float walkfromwp) { - return navigation_findnearestwaypoint_withdist(ent, walkfromwp, 1050); + entity wp = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, world); + if (autocvar_g_waypointeditor_auto) + { + entity wp2 = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, wp); + if (!wp2) + wp.wpflags |= WAYPOINTFLAG_PROTECTED; + } + return wp; } // finds the waypoints near the bot initiating a navigation query diff --git a/qcsrc/server/bot/waypoints.qc b/qcsrc/server/bot/waypoints.qc index 78bf0f264..da0b35089 100644 --- a/qcsrc/server/bot/waypoints.qc +++ b/qcsrc/server/bot/waypoints.qc @@ -543,6 +543,46 @@ void waypoint_load_links_hardwired() dprint(".waypoints.hardwired\n"); } +entity waypoint_get_link(entity w, float i) +{ + switch(i) + { + case 0:return w.wp00; + case 1:return w.wp01; + case 2:return w.wp02; + case 3:return w.wp03; + case 4:return w.wp04; + case 5:return w.wp05; + case 6:return w.wp06; + case 7:return w.wp07; + case 8:return w.wp08; + case 9:return w.wp09; + case 10:return w.wp10; + case 11:return w.wp11; + case 12:return w.wp12; + case 13:return w.wp13; + case 14:return w.wp14; + case 15:return w.wp15; + case 16:return w.wp16; + case 17:return w.wp17; + case 18:return w.wp18; + case 19:return w.wp19; + case 20:return w.wp20; + case 21:return w.wp21; + case 22:return w.wp22; + case 23:return w.wp23; + case 24:return w.wp24; + case 25:return w.wp25; + case 26:return w.wp26; + case 27:return w.wp27; + case 28:return w.wp28; + case 29:return w.wp29; + case 30:return w.wp30; + case 31:return w.wp31; + default:return world; + } +} + // Save all waypoint links to a file void waypoint_save_links() { @@ -565,44 +605,7 @@ void waypoint_save_links() for(i=0;i<32;++i) { // :S - link = world; - switch(i) - { - // for i in $(seq -w 0 31); do echo "case $i:link = w.wp$i; break;"; done; - case 0:link = w.wp00; break; - case 1:link = w.wp01; break; - case 2:link = w.wp02; break; - case 3:link = w.wp03; break; - case 4:link = w.wp04; break; - case 5:link = w.wp05; break; - case 6:link = w.wp06; break; - case 7:link = w.wp07; break; - case 8:link = w.wp08; break; - case 9:link = w.wp09; break; - case 10:link = w.wp10; break; - case 11:link = w.wp11; break; - case 12:link = w.wp12; break; - case 13:link = w.wp13; break; - case 14:link = w.wp14; break; - case 15:link = w.wp15; break; - case 16:link = w.wp16; break; - case 17:link = w.wp17; break; - case 18:link = w.wp18; break; - case 19:link = w.wp19; break; - case 20:link = w.wp20; break; - case 21:link = w.wp21; break; - case 22:link = w.wp22; break; - case 23:link = w.wp23; break; - case 24:link = w.wp24; break; - case 25:link = w.wp25; break; - case 26:link = w.wp26; break; - case 27:link = w.wp27; break; - case 28:link = w.wp28; break; - case 29:link = w.wp29; break; - case 30:link = w.wp30; break; - case 31:link = w.wp31; break; - } - + link = waypoint_get_link(w, i); if(link==world) continue; @@ -876,7 +879,7 @@ float botframe_autowaypoints_fixdown(vector v) return 1; } -float botframe_autowaypoints_createwp(vector v, entity p, .entity fld) +float botframe_autowaypoints_createwp(vector v, entity p, .entity fld, float f) { entity w; @@ -890,7 +893,7 @@ float botframe_autowaypoints_createwp(vector v, entity p, .entity fld) w = find(w, classname, "waypoint"); } - waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, 0)); + waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, f)); return 1; } @@ -916,7 +919,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en if(wp) { - // if any WP w fulfills wp -> w -> porg, then switch from wp to w + // if any WP w fulfills wp -> w -> porg and w is closer than wp, then switch from wp to w // if wp -> porg, then OK float maxdist; @@ -993,7 +996,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en t = (tmin + tmax) * 0.5; o = antilag_takebackorigin(p, time - t); if(!botframe_autowaypoints_fixdown(o)) - return -1; + return -2; o = trace_endpos; if(wp) @@ -1032,7 +1035,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en } print("spawning a waypoint for connecting to ", etos(wp), "\n"); - botframe_autowaypoints_createwp(o, p, fld); + botframe_autowaypoints_createwp(o, p, fld, 0); return 1; } @@ -1051,7 +1054,78 @@ void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld) print("emergency: got no good nearby WP to build a link from, starting a new chain\n"); if(!botframe_autowaypoints_fixdown(p.origin)) return; // shouldn't happen, caught above - botframe_autowaypoints_createwp(trace_endpos, p, fld); + botframe_autowaypoints_createwp(trace_endpos, p, fld, WAYPOINTFLAG_PROTECTED); +} + +void botframe_deleteuselesswaypoints() +{ + entity w, w1, w2; + float i, j, k; + for (w = world; (w = findfloat(w, bot_pickup, TRUE)); ) + { + // NOTE: this protects waypoints if they're the ONLY nearest + // waypoint. That's the intention. + navigation_findnearestwaypoint(w, FALSE); // Walk TO item. + navigation_findnearestwaypoint(w, TRUE); // Walk FROM item. + } + for (w = world; (w = find(w, classname, "waypoint")); ) + { + w.wpflags &= ~WAYPOINTFLAG_USEFUL; + // WP is useful if: + if (w.wpflags & WAYPOINTFLAG_ITEM) + w.wpflags |= WAYPOINTFLAG_USEFUL; + if (w.wpflags & WAYPOINTFLAG_TELEPORT) + w.wpflags |= WAYPOINTFLAG_USEFUL; + if (w.wpflags & WAYPOINTFLAG_PROTECTED) + w.wpflags |= WAYPOINTFLAG_USEFUL; + // b) WP is closest WP for an item/spawnpoint/other entity + // This has been done above by protecting these WPs. + } + // c) There are w1, w, w2 so that w1 -> w, w -> w2 and not w1 -> w2. + for (w1 = world; (w1 = find(w1, classname, "waypoint")); ) + { + if (w1.wpflags & WAYPOINTFLAG_PERSONAL) + continue; + for (i = 0; i < 32; ++i) + { + w = waypoint_get_link(w1, i); + if (!w) + break; + if (w.wpflags & WAYPOINTFLAG_PERSONAL) + continue; + if (w.wpflags & WAYPOINTFLAG_USEFUL) + continue; + for (j = 0; j < 32; ++j) + { + w2 = waypoint_get_link(w1, i); + if (!w2) + break; + if (w2.wpflags & WAYPOINTFLAG_PERSONAL) + continue; + for (k = 0; k < 32; ++k) + { + if (waypoint_get_link(w1, k) == w2) + continue; + // IF WE GET HERE, w is proven useful + // to get from w1 to w2! + w.wpflags |= WAYPOINTFLAG_USEFUL; + continue; + } + } + } + } + for (w = world; (w = find(w, classname, "waypoint")); ) + { + if (!(w.wpflags & WAYPOINTFLAG_USEFUL)) + { + printf("Removed a waypoint at %v. Try again for more!\n", w.origin); + te_explosion(w.origin); + waypoint_remove(w); + break; + } + } + for (w = world; (w = find(w, classname, "waypoint")); ) + w.wpflags &= ~WAYPOINTFLAG_USEFUL; // temp flag } void botframe_autowaypoints() @@ -1066,5 +1140,7 @@ void botframe_autowaypoints() botframe_autowaypoints_fix(p, TRUE, botframe_autowaypoints_lastwp1); //te_explosion(p.botframe_autowaypoints_lastwp0.origin); } + + botframe_deleteuselesswaypoints(); } diff --git a/qcsrc/server/bot/waypoints.qh b/qcsrc/server/bot/waypoints.qh index 5a75551d2..9ac92405d 100644 --- a/qcsrc/server/bot/waypoints.qh +++ b/qcsrc/server/bot/waypoints.qh @@ -7,6 +7,8 @@ const float WAYPOINTFLAG_ITEM = 4194304; const float WAYPOINTFLAG_TELEPORT = 2097152; const float WAYPOINTFLAG_NORELINK = 1048576; const float WAYPOINTFLAG_PERSONAL = 524288; +const float WAYPOINTFLAG_PROTECTED = 262144; // Useless WP detection never kills these. +const float WAYPOINTFLAG_USEFUL = 131072; // Useless WP detection temporary flag. // fields you can query using prvm_global server to get some statistics about waypoint linking culling float relink_total, relink_walkculled, relink_pvsculled, relink_lengthculled; -- 2.39.2