Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 11 to 20 of 24

Thread: August 24 Bot Update

  1. #11
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,017
    Quote Originally Posted by DzeeRay View Post
    great addition to the api thank you, i just want to report a visual bug relating DebugDraw* functions (the same for
    dota_bot_debug_team) the lines and circles are drawn with a huge offset and the entier thing is croped in the right and bottom, (it may be related to my local machine because no one reported this).
    Try this command in the console:
    Code:
    mat_viewportscale 1
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  2. #12
    Basic Member
    Join Date
    Dec 2016
    Posts
    731
    Quote Originally Posted by ChrisC View Post
    Currently they last forever, but yes I could definitely add an expiration duration that you could supply when you added one. I could definitely see that being useful.
    Can I suggest that instead we are allowed to pass a function pointer to an assertion function (aka evaluation function) - that takes 1 argument (of my choosing) - or an arbitrary number of arguments really... not sure it matters? What I mean is, a function of my choosing that is evaluated to a true or false return value.

    That way I could do exactly what you suggest and make a simple expiration check function for some avoidance zones based on game time.
    Code:
    function TimeBasedAssertion(fTime)
        return GameTime() >= fTime
    end
    However I could also make Avoidance Zones based on other variables. For example: an enemy tower avoidance zone on the assertion that enemy tower health is >= 1.
    Code:
    function HealthBasedAssertion(hTower)
        return hTower:GetHealth() >= 1
    end
    Also, more interesting, it would also allow me to be more creative and make conditional avoidance zone (mark the Dire Safelane Jungle a huge avoidance zone if I don't see the midlaner or offlaner and have no vision via wards in their jungle) - the assertion function could be something like:
    (pseudocode)
    Code:
    function avoidEnemySafelaneJungleAssertion(fTime)
        return midlaneEnemyNotVisible(fTime) and offlaneEnemyNotVisible(fTime)
    end
    With this last example it might be helpful if the avoidance zone never really gets "deleted" but rather is considered or not considered based on the assertion evaluation.

    Quote Originally Posted by ChrisC View Post
    There's no way to iterate through them currently other than you building a table of them as you add them. If it would be useful, I could add an iterator.
    Of course that would be useful, although considering the above it might not be necessary.
    Last edited by nostrademous; 08-26-2017 at 06:59 AM.

  3. #13
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,017
    Quote Originally Posted by nostrademous View Post
    Can I suggest that instead we are allowed to pass a function pointer to an assertion function (aka evaluation function) - that takes 1 argument (of my choosing) - or an arbitrary number of arguments really... not sure it matters? What I mean is, a function of my choosing that is evaluated to a true or false return value.
    So you want something similar to this pseudo-context?
    Code:
    local TowerCustomAZ = nil;
    local TimerCustomAZ = nil;
    
    local function EvalTempAZTower (tParams)
        return (tParams.tower~= nil and tParams.tower:GetHealth() > 0)
    end
    
    local function EvalTempAZTime (tParams)
        return (tParams.LastSeenTime > 5);
    end
    
    local function AddTempAZ ()
        local unit = GetTower(GetOpposingTeam(), 1);
        local location = unit:GetLocation();
        location.Z = 1000; -- tower range + 100
    
       TowerCustomAZ = AddAvoidanceZone(location, function () EvalTempAZTower ( { ["tower"] = unit} ) );
    
        unit = GameTime() + GetLastRoamTargetLastSeenTime() + lastSeenThreshold;
        location = GetSomeEnemyLastLocation();
        location.Z = 500;
       TimerCustomAZ = AddAvoidanceZone(location, function () EvalTempAZTime ( { ["Unit"] = unit, ["LastSeenTime"] = GameTime() } ) );
    end
    ... and if the eval functions return false (for example), then the engine automatically calls the AZ removal. Right?

    If so, that'd mean that the engine would have to remember the table you passed as param for each AZ callback. But I can definitely see some potential in such a design
    I mostly wanted it for wards but your idea can expand it even further.
    Last edited by The Nomad; 08-26-2017 at 07:39 AM.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  4. #14
    Basic Member
    Join Date
    Dec 2016
    Posts
    731
    Quote Originally Posted by The Nomad View Post
    ... and if the eval functions return false (for example), then the engine automatically calls the AZ removal. Right?
    Sure.

    Quote Originally Posted by The Nomad View Post
    If so, that'd mean that the engine would have to remember the table you passed as param for each AZ callback.
    Not necessarily. It really depends where the evaluation happens. Currently no timers exist so the remove of any AZ would have to be done by player code. What I suggest is the same with the addition that a termination assertion is embodied with the AZ so that in our bot code we don't have to iterate all the AZ as we have a reference to the termination function which was established when we created the AZ in the first place. This would allow re-use of typical AZ termination assertions (like timers) if it made a new copy of the function when associating with an AZ (rather then just passing it by reference).

    The iteration over all the AZ's and their associated termination assertions could just be another pass complete as part of the player code time (most likely prior to each bot's Think() execution).

    The table we pass would only need to be remembered if the termination assertion evaluation is done on the server code, and not as part of player code.

  5. #15
    Basic Member
    Join Date
    Dec 2016
    Posts
    32
    Quote Originally Posted by The Nomad View Post
    Try this command in the console:
    Code:
    mat_viewportscale 1
    thank you very much sir,the command fixed the problem, i noticed that its the same as "settings>video>game screen render quality".

  6. #16
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,017
    Quote Originally Posted by nostrademous View Post
    Not necessarily. It really depends where the evaluation happens. Currently no timers exist so the remove of any AZ would have to be done by player code. What I suggest is the same with the addition that a termination assertion is embodied with the AZ so that in our bot code we don't have to iterate all the AZ as we have a reference to the termination function which was established when we created the AZ in the first place. This would allow re-use of typical AZ termination assertions (like timers) if it made a new copy of the function when associating with an AZ (rather then just passing it by reference).

    The iteration over all the AZ's and their associated termination assertions could just be another pass complete as part of the player code time (most likely prior to each bot's Think() execution).

    The table we pass would only need to be remembered if the termination assertion evaluation is done on the server code, and not as part of player code.
    Not sure I made myself clear yes, the function is passed but it will be saved as a pointer deep down in the native code. The params you pass it would not be part of it unless they are explicitly saved separately along with the callback in the engine. I was talking about the C++ part, not the Lua part. But that was just a remark

    Quote Originally Posted by ChrisC View Post
    Bot pathfinding uses a first-pass pathfind though the bot's pathing grid, using the weights from the built-in bot avoidance system -- it makes pathing through towers, etc more expensive. "Normal" is just a straight-up right-click.
    When is the avoidance system used? If I ask a bot to tower dive, they won't avoid it, but will gladly feed. How would I access the weight-vs-desire algo to make a bot avoid danger areas when moving? Also, is the AttackMove() action using the same pathfinding algo as MoveToLocation() ? What about MoveToUnit() ?

    Quote Originally Posted by ChrisC View Post
    The intention of the default-bot avoidance zones is that they're applied to all bots on a team, and have some information contained within them ("does physical damage", "does magical damage") etc, and different bots would react to them differently based on their details (tanky guy can ignore physical damage, if you have bkb active you can ignore the magic ones, etc). In practice, I don't think this actually works that well because they don't really capture the full breadth of the circumstances of avoidance for a given bot. I suspect that managing a moment-to-moment "absolutely do not path through this zone" list for each bot, along with a few generic "this is so bad that one one should go through it" zones works better for the specific details of what each bot wants to avoid. So that's the idea behind these new avoidance zones (and if I had the built-in ones to do over, I think that's how I'd write them).
    Is fissure considered an avoidance zone (in the native AZ functions, not the custom ones) ?
    While similar to Ice Path or Macropyre, those do continous damage, while fissure deals damage only when casting and then is just an annoying impassable wall If not, how do I detect fissure?

    Quote Originally Posted by ChrisC View Post
    So I guess my recommendation is to punt on the old avoidance stuff entirely.
    Oh I had a look at the code more closely and I was actually thinking of spicing it up by mixing them. The only thing that stopped me is that the "native" (or should I call them "old" from now on ? ) AZ don't have any expiration time either. Since you said we should either drop them or that if we were to aggressively use it, you'd redo them, I am not sure if you want to invest more time into them (and ATM I don't know if anyone other than nostrademous is using the old AZ), but if it is not too much effort, could you add something like time_remianing or something like that to the old AZ structure?

    If you do plan to update the new AZ with the suggestions you got from me and nostrademous (and most likely others that will start using them) others might want to take advantage of the old ones somehow too (even if to manually to the physical vs magical logic since some plan to upgrade to ML from the SBM logic) and I don't know how much overhead GetAvoidanceZones() since I haven't tried it yet in an actual 60+ minute game. Then again, if iti is too complicated or you say that GetAvoidanceZones() doesn't draw out too much performance power, I guess I can just call it and iterate through it each frame and sync it with AddAvoidanceZone() and RemoveAvoidanceZone().
    Last edited by The Nomad; 08-27-2017 at 12:44 AM.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  7. #17
    @ChrisC: I tried the path finding functions. Can you please explain the followings a bit:

    1. Sometimes when I generate a path and pass it to the Action_MovePath, the bot gets stuck or the function doesn't return a path (I do that in every frame, and the bot is not in any of the avoidance regions). Can you do a quick check if there is a problem with your code that can cause this? Or doing this in every frame causes a problem?

    2. Why do you need a function in generating path function instead of returning the path and its length? Are the paths generated in parallel (i.e. in a separate thread from the actual script)?

    3. What are the cases in which generate-path fails? (for instance, does it always fail if the beginning/end is in an avoidance zone?)

    4. How computationally heavy is the generate path function? Is it noticeably faster if we add the avoidance zones instead of using them in each call manually?

    5. For all the cases where there exists a valid path that avoids all the zones, does the generate path function returns an actual valid path (at least in theory)? Or is it a heuristic that may or may not generate a path conditional on the existence? If it doesn't have such guarantees, do you know of some scenarios that it doesn't generate a path?

  8. #18
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,017
    Quote Originally Posted by Platinum_dota2 View Post
    3. What are the cases in which generate-path fails? (for instance, does it always fail if the beginning/end is in an avoidance zone?)
    This interests me as well. I am curious about reachability (such as if trees are in the way even thought the "target" location is passable (or visible).
    There is also the difference in how a bot controlled hero considers a target destination reachable vs the way a human controlled hero does (e.g. a human controlled one can approximate that hey reached the target within a threshold while a bot insists that their location and the target location must be the same for it to be considered "reached").
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  9. #19
    Basic Member
    Join Date
    Dec 2016
    Posts
    32
    it seems that the pathing grid resolution is a little bit small which cause the pathfinding to fail on a lot of juking spots, also the actual state of trees is not considered (the pathfinder will avoid chopped trees).
    i also hope the pathfinding (optionaly) consider units too.(maybe this will help a shapeshifted bot lycan going for a kill while bodyblocked by a creep).
    Last edited by DzeeRay; 09-13-2017 at 01:37 AM.

  10. #20
    Valve Developer
    Join Date
    Sep 2011
    Posts
    1,704
    Quote Originally Posted by Platinum_dota2 View Post
    @ChrisC: I tried the path finding functions. Can you please explain the followings a bit:

    1. Sometimes when I generate a path and pass it to the Action_MovePath, the bot gets stuck or the function doesn't return a path (I do that in every frame, and the bot is not in any of the avoidance regions). Can you do a quick check if there is a problem with your code that can cause this? Or doing this in every frame causes a problem?

    2. Why do you need a function in generating path function instead of returning the path and its length? Are the paths generated in parallel (i.e. in a separate thread from the actual script)?

    3. What are the cases in which generate-path fails? (for instance, does it always fail if the beginning/end is in an avoidance zone?)

    4. How computationally heavy is the generate path function? Is it noticeably faster if we add the avoidance zones instead of using them in each call manually?

    5. For all the cases where there exists a valid path that avoids all the zones, does the generate path function returns an actual valid path (at least in theory)? Or is it a heuristic that may or may not generate a path conditional on the existence? If it doesn't have such guarantees, do you know of some scenarios that it doesn't generate a path?
    1. & 2. Pathfinding is expensive and the pathfinder has a limited amount of time it's allowed to work in any given frame, so path generation is asynchronous and might take multiple frame to complete. In addition, it only allows a few (I believe 5) pathfinds to be in flight at once. Your best bet is to keep track of your location and your target location, and only pathfind when they've deviated significantly.

    3. If there are no paths to the location, which includes the starting or ending locations being in an avoidance zone.

    4. Long pathfinds can definitely be expensive, but avoidance zones don't change it THAT much, and it doesn't really matter at all if they're persistent or passed-in avoidance zones. Tens of avoidance zones is probably free-ish. Hundreds probably start impacting perf a bit, but given that the pathfinder has a per-frame cap, it just means that it will take more frames to get back to you with your path.

    5. I believe it should generate a valid path, where a valid path exists. If it doesn't, I'd consider that a bug.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •