Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autodrive v2 #49772

Merged
merged 13 commits into from
Jul 31, 2021
Merged

Autodrive v2 #49772

merged 13 commits into from
Jul 31, 2021

Conversation

eltank
Copy link
Contributor

@eltank eltank commented Jul 9, 2021

Summary

Features "Improved autodrive with pathfinding (Autodrive v2)"

Purpose of change

This is the first PR for the "Fast travel" project, #49455. It is a partial rewrite of the autodrive system that does pathfinding at the map tile level in order to avoid obstacles, which greatly reduces player tedium when traveling long any distance in a vehicle. Demo videos can be found below.

Task list:

  • Precompute and cache reachability graph
  • Drive along an approximate-best collision-free path to reach the next OMT
  • Optimize for performance
  • Try to leave extra room when navigating around obstacles
  • Handle NPC drivers
  • Support boats and aircraft (current z-level only)
  • Support amphibious navigation
  • Handle poor visibility and no visibility
  • Anticipate possible collisions due to moving creatures (and bail out)
  • Travel faster than the minimum speed (1 tile/turn)
  • Try to avoid dead ends by looking ahead one extra OMT

Describe the solution

The main change is in vehicle::do_autodrive(), which simulates driving actions taken by the player character for 1 turn with the goal of eventually traversing a sequence of OMTs selected via the overmap UI in order to arrive at some destination (do_autodrive is called repeatedly from autodrive_activity_actor::do_turn).

Unlike the old code which simply steered towards the next OMT and blindly traveled in a straight line (often crashing into things or bailing out), the new code analyzes the map tiles along the way and uses A* to find a path around any obstacles.

Data structures:

  • vehicle profile: a scanline convex hull representation of the map tiles occupied by the vehicle at each of the 24 possible rotations relative to the pivot point
  • view map: a 2D array corresponding to the map tiles in the current and all neighboring OMTs; records which tiles can be driven on and which are obstacles
  • nav map: a 2D array for the map tiles in the current OMT and part of the next OMT; records which tiles the vehicle's pivot point can occupy safely for all possible rotations (making it a 3D array)
  • node address: a tuple of x and y coordinates for the vehicle pivot point plus vehicle rotation (the 3 coordinates of the nav map)
  • navigation node: contains the address of the node, the cost of the best path to reach it, the address of the previous node on that path and some data needed to compute the next node (such as the number of tiles driven in the current direction, which is important when the direction angle is not a multiple of 45 degrees)
  • scored address: the address of a node to consider (a node in the "open set" per A* terminology) and its heuristic value describing how close it is to the destination (the next OMT) and whether the vehicle is pointing in the right direction

The profiles, maps and best path are stored in a cache (populated once during OMT transition). In between OMT transitions, the vehicle simply follows the previously found path tile by tile, steering as necessary in order to achieve the predetermined orientation at each step. The path is usually found very quickly (~20 nodes explored) when the area is clear. In the worst case (no possible path can be found) the algorithm can explore over 10000 nodes before giving up, but it's so fast that even such a high number of iterations does not slow the game noticeably (on my computer at least).
Just like the previous autodrive system, all driving actions are performed by calling the same function that handles player input during manual driving (pldrive).
Note that the maximum vehicle speed (in-game, not real-time) achieved by this initial implementation is very low. This will be improved later. However, I believe that even with these limitation the system is better than what we have now.

Describe alternatives you've considered

My previous idea for fast travel (also described in #49455) was to record the path taken by the player while driving a vehicle in order to be able to replay it later. However, that solution is far inferior in terms of usability and versatility.

Testing

Playtesting. Lots of playtesting.

Additional context

Here are some videos I recorded earlier. This was before I implemented "leave extra room when navigating around obstacles", so there are a few close shaves (safe but maybe a bit unrealistic, which is why I made the change).

Driving around a roadblock:

roadblock.mp4

Driving 216 overmap tiles through multiple towns:

longdist1.mp4

Driving a bus out of town:

bus1.mp4

Riding a bike. This video was made after the "extra room around obstacles" change.

bike1.mp4

More videos can be found in comments below.

@actual-nh actual-nh added <Enhancement / Feature> New features, or enhancements on existing Quality of Life QoL: degree to which players are comfortable, and able to enjoy CDDA Vehicles Vehicles, parts, mechanics & interactions labels Jul 9, 2021
@actual-nh actual-nh requested a review from mlangsdorf July 9, 2021 08:02
@actual-nh actual-nh added the [C++] Changes (can be) made in C++. Previously named `Code` label Jul 9, 2021
@meelock
Copy link
Contributor

meelock commented Jul 9, 2021

I would say that the collision detection and avoiding seems almost too good, like auto-drive makes the player an inhuman driving god. Not to say that I'm not in favor of such a change though, as it will make one of the most tedious portions of the game more livable.

I think finally having proper collision avoiding tech means that having AI controlled vehicles may be more reasonable, I think it would be really neat to have AI controlled roving gangs, but I don't know what that would be like to implement.

Maybe there could even be the ability to set up cargo transport in real time, but all of this would have to come after NPC AI is de-jankified.

@PatrikLundell
Copy link
Contributor

@meelock: Any NPC driving using logic similar to this would require the NPCs to have reality bubbles of their own.

@eltank
Copy link
Contributor Author

eltank commented Jul 9, 2021

I would say that the collision detection and avoiding seems almost too good, like auto-drive makes the player an inhuman driving god.

The reason driving manually in CDDA is difficult is because the vehicle controls are unintuitive, mainly because vehicles deform in difficult-to-predict ways when rotated but also because a keyboard is inferior to steering wheel + pedals as a vehicle control mechanism. Imagine yourself driving a real vehicle in a post-apocalyptic world. You wouldn't have any problems going around obstacles, especially at low speeds. In my opinion this PR improves realism by allowing your avatar to perform a task that is easy in reality but artificially difficult for you as the player.

I think finally having proper collision avoiding tech means that having AI controlled vehicles may be more reasonable

My plan is to make this system handle driving simulations for any in-game character (not just the player character). However, I think I'll let other folks figure out how to make use of that functionality.
Here's one idea: Imagine telling an NPC via radio to come pick you up (in a vehicle parked at the base camp) if you're stranded.

Any NPC driving using logic similar to this would require the NPCs to have reality bubbles of their own

Having a single reality bubble is not a big problem. Like many other simulation games, CDDA could use a different, simplified simulation mechanism when NPCs are outside of it.

@RenechCDDA
Copy link
Member

Can I ask if those video examples were real-time recorded? Auto-drive "v1", even when it's not careening wildly into obstacles, has a horrible horrible time about shifting up/down gears/speed and making sharp 90 degree turns jigsawing back and forth across roads. Part of the reason why even when it is safe it literally takes longer than just driving yourself.

V2 looks extremely promising though. I've seen a lot of questions about auto-drive recently and I hope soon I'll be able to answer them with "Yep, it works great now!"

@acepleiades
Copy link
Contributor

With graphical overmaps fleshed out this would be such an amazingly fun thing to have

@actual-nh
Copy link
Contributor

actual-nh commented Jul 9, 2021

Regarding the extra room around (non-moving!) obstacles: Perhaps have this decrease with driving skill? And/or increase with speed?

@meelock
Copy link
Contributor

meelock commented Jul 9, 2021

I personally would very much appreciate the functionality to allow auto-drive to go off of roads when need be, but I doubt that is as important as most other things.

@eltank
Copy link
Contributor Author

eltank commented Jul 9, 2021

Can I ask if those video examples were real-time recorded?

Yes, the videos were recorded in real-time. I'm not a video editing wiz, so all I did was crop, resize and compress using Handbrake.

Regarding the extra room around (non-moving!) obstacles: Perhaps have this decrease with driving skill? And/or increase with speed?

The way it works is it assigns a higher cost to paths that cause a "close shave". If there's an easy way to go around obstacles with 1 tile of extra space (by steering slightly away), it'll do that instead. I think this more closely matches what a human driver would do (why risk collision/scraping your car if you can give yourself a bit of a buffer zone). But if the only way through is to squeeze through a narrow gap or it's too inconvenient to go around, it'll do that (again, what a human driver would do). I uploaded a new video of a bike ride demonstrating this feature.
I think this behavior doesn't depend on skill level. What will change based on skill is the speed. At higher skill you can turn faster, so you could also drive faster around obstacles (not in this PR).

I personally would very much appreciate the functionality to allow auto-drive to go off of roads when need be, but I doubt that is as important as most other things.

That's on the project roadmap (#49455) and something I consider a high priority because in my recent playthroughs and debug runs I have often found that in order to get to the Refugee Center I would either need to drive through several large cities (full of zombies) OR take a shortcut through some (mostly empty) fields. Most times using the evac shelter console fails to even find a path to the Center via the road network so the only way to reach it is to go off-road.

@PatrikLundell
Copy link
Contributor

I think there's some work on improving the road network to connect places in a more logical fashion, rather than the very sparse network we have now, but driving over open terrain around cities when possible would definitely be useful regardless. One problem with that is how to determine whether to go through or around, and how to tell the auto route logic when to take the longer route around cities (or, in the general case, anything, such as turrets or ant infested terrain).

@eltank
Copy link
Contributor Author

eltank commented Jul 9, 2021

I think there's some work on improving the road network to connect places in a more logical fashion, rather than the very sparse network we have now, but driving over open terrain around cities when possible would definitely be useful regardless. One problem with that is how to determine whether to go through or around, and how to tell the auto route logic when to take the longer route around cities (or, in the general case, anything, such as turrets or ant infested terrain).

Quoting from the project roadmap: "Allow toggling OMTs that should be avoided by autodrive pathfinding". This would be done from the overmap UI by pressing a key (similar to how you can mark OMTs as "explored" today). So if you disallow the road tiles going into a city it'll not go through that city. If you want to give the city a wide berth you may need to disallow a lot of the field tiles around it (tedious but possible).
Another option is to forbid travel through OMTs that you have never been on before. Then after manually driving around a city auto-drive would follow the same path you took when going through that area. I think this option would have to be toggle-able (default on), probably also in the overmap UI.

@eltank eltank force-pushed the better_autodrive branch from 5730c2b to 72c3057 Compare July 9, 2021 19:27
@eltank
Copy link
Contributor Author

eltank commented Jul 10, 2021

Hmm, I found a bug in the autodrive action code, one of the parts that I was planning to reuse without changing. It "cheats" by allowing you to turn 3 times per second (or more) even when you don't have the moves for it. I'm including a fix for that in this PR.

@acepleiades
Copy link
Contributor

What happens when you autodrive while crouched inside the vehicle or driving a vehicle that blocks your vision forward?

@eltank
Copy link
Contributor Author

eltank commented Jul 10, 2021

What happens when you autodrive while crouched inside the vehicle or driving a vehicle that blocks your vision forward?

Currently visibility is not taken into account, so you can drive blind. This is why "Handle visibility issues" is on the task list.
This is addressed now. If you can't see what's in front of you autodrive will stop. Unless you have map memory for the area, then it'll go, but won't avoid creatures so you may hit something (which will cancel autodrive).

@eltank
Copy link
Contributor Author

eltank commented Jul 10, 2021

Just added support for watercraft and aircraft.

boat1.mp4
chopper1.mp4

@eltank
Copy link
Contributor Author

eltank commented Jul 10, 2021

Also amphibious vehicles, because why not.

amphib1.mp4

@eltank eltank force-pushed the better_autodrive branch from 708fc96 to 50d6908 Compare July 10, 2021 23:23
Copy link
Contributor

@actual-nh actual-nh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice progress!

@eltank eltank force-pushed the better_autodrive branch from 3fbc7f0 to 3a8ba98 Compare July 11, 2021 06:17
@eltank
Copy link
Contributor Author

eltank commented Jul 11, 2021

Rebased on HEAD to pick up unlimited map memory (#47253) which will be useful for the visibility checks (what I'm working on next). Also squashed the commits while I was at it.

@Tairesh
Copy link
Contributor

Tairesh commented Jul 11, 2021

I see you are still using simple_pathfinding to find the way on the global map, it makes weird curves (see example below) and uses 4-dir movement instead of 8-dir. It is partially fixed in BN fork: https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/src/simple_pathfinding.h but it still makes strange ways even with diagonals.
image

Can you please implement adequate 8-dir movement, it's silly when a vehicle (especially boats and helicopters) moves like this:

***********X
*
*
*
*
*
*
*
*
@

instead of this:

        X
       *
      *
     *
    *
   *
  *
 *
@

@eltank
Copy link
Contributor Author

eltank commented Jul 11, 2021

I see you are still using simple_pathfinding to find the way on the global map, it makes weird curves (see example below) and uses 4-dir movement instead of 8-dir.

That's a good point. In CDDA vehicles travel faster diagonally (at the moment; this could change), so in order to reach your destination sooner that kind of movement should be prioritized, especially for air and water navigation.
Autodrive requires that the OMT path be constructed using 4-dir movement and I'm not planning to change that. However, the following path is equivalent to the one you drew earlier, in that it will cause the vehicle to drive at about a 45 degree angle the whole time. That's because autodrive doesn't target the midpoints of OMTs, but rather the midpoints of the edges between OMTs, which in this case form a straight diagonal line.

        X
       **
      **
     **
    **
   **
  **
 **
 @

I haven't touched the overmap pathfinding yet, but I will later. I've added this idea to the project tracker (#49455): "Prefer faster (diagonal) paths when pathing through air, lakes or fields"

@eltank
Copy link
Contributor Author

eltank commented Jul 11, 2021

Added terrain visibility checks. Without lights you can only drive as long as you have map memory (but risk colliding with unseen creatures). If you turn on the headlights you can go further (and can see creatures in your path). Demo below:

night_driving1.mp4

@PatrikLundell
Copy link
Contributor

Does the light check include turning the lights on when needed, or is that something the player has to do? You may start out while it's light enough to see, but might not reach the destination until it's fully dark.

@eltank
Copy link
Contributor Author

eltank commented Jul 11, 2021

Does the light check include turning the lights on when needed, or is that something the player has to do? You may start out while it's light enough to see, but might not reach the destination until it's fully dark.

Turning on the headlights is something the player has to do. I suppose it could be automated, but maybe the player doesn't want the lights on for some reason (e.g. the battery is almost drained and they need to maximize the energy available for the motor). It's also difficult to know which lights to turn on when there are multiple types.

Probably the best thing to do would be a prompt like "It is too dark to see clearly. Stop driving? (y/n)" when you can't see the tiles in front of the car. I could add that as part of the collision detection (since unseen tiles are a collision hazard).
I see one problem with that, though: a typical 4-tile-wide car in CDDA has its headlights arranged in such a way that the 2 tiles in front of the car between the headlights are not illuminated. This would always cause a prompt even when the lights are on, unless you have sufficient perception / night vision to see those tiles.

eltank added 2 commits July 29, 2021 16:52
Introduce vehicle::get_debug_overlay_data() which returns a vector of
vehicle-relative colored annotations to display.
The optimization is to not do any work when vehicle debug is not on.
@eltank eltank force-pushed the better_autodrive branch from f2d133c to 3b7404d Compare July 29, 2021 23:54
@eltank
Copy link
Contributor Author

eltank commented Jul 30, 2021

I'm not sure what else needs to happen to allow this to be merged. Assuming it's held up by code reviews?

On the playtesting side, I've been using this for over a week in a non-debug playthrough using a custom build based on 0.F + various patches including this PR and it's been extremely useful in reducing keypress tedium (also, haven't had a single collision). It was very limiting without the ability to drive off-road so I made a quick hack in the overmap pathfinding code (about 20 lines), which I'm not sure whether to include in this PR or not. IMO the overmap pathfinding is buggy and inefficient so I'd like to do much more than a quick hack but obviously not in this PR.
Anyway, here's a video of offroad driving avoiding trees, critters and rocks in my debug world.

offroad1.mp4

@eltank eltank force-pushed the better_autodrive branch from 3b7404d to 233e879 Compare July 30, 2021 01:47
@eltank
Copy link
Contributor Author

eltank commented Jul 30, 2021

I just found out the hard way that autodrive ignores landmines. Fortunately it's trivial to fix, just a couple of lines added to check_is_drivable(), and I've included the fix in this PR. Both pathfinding and collision detection use check_is_drivable so if you are somehow able to spot a trap while driving then collision detection will save you even if the planned path would have taken you over a trap.
Now if you choose to drive through a minefield with a small enough vehicle you'll drive around the mines that you see or remember seeing before. This requires you to get out of the vehicle and carefully survey the area first.

@anothersimulacrum
Copy link
Member

@pjf I know you're playing with existing PRs in your game, perhaps this might interest you?

@actual-nh
Copy link
Contributor

actual-nh commented Jul 30, 2021

@pjf I know you're playing with existing PRs in your game, perhaps this might interest you?

#50176 is one/another that playtesting is highly desirable for.

@esotericist
Copy link
Contributor

I'm not sure what else needs to happen to allow this to be merged. Assuming it's held up by code reviews?

mostly this, honestly. it's a pretty big PR, and i'm not aware of any of the merge team in a position to go over it right away. 😞 we definitely want this in the game, but we (usually) try not to just merge things without one of the mergers being comfortable saying "yeah, this is right enough". that sometimes results in things like this sitting admittedly longer than they should.

all that being said, more playtesting will definitely not hurt, and we've gotten some useful reviews from other folks, both of which reduces the burden on the final merger.

Now if you choose to drive through a minefield with a small enough vehicle you'll drive around the mines that you see or remember seeing before. This requires you to get out of the vehicle and carefully survey the area first.

this sounds incredibly awesome. 🤘

thank you for persevering on this and other things. you're doing great work.

i wish i could give this the attention it deserves, but i myself am dealing with health issues (both personally and for a cat rescue), so i've mostly been absent lately. mostly i've been trying to keep an eye on this to make sure it doesn't get forgotten (and to ensure you know it hasn't been forgotten).

@kevingranade kevingranade merged commit a287fad into CleverRaven:master Jul 31, 2021
@kevingranade
Copy link
Member

This is simply amazing work.

@esotericist
Copy link
Contributor

i stand corrected. glad to have been wrong

@eltank
Copy link
Contributor Author

eltank commented Jul 31, 2021

Awesome, thanks! I'll get started on the follow-up work. Next up: overmap pathfinding.

@eltank eltank deleted the better_autodrive branch July 31, 2021 11:32
@kevingranade
Copy link
Member

Something I noticed is that since you've implemented size-and-orientation aware A*, you've essentially also implemented pathfinding for multi-tile monsters.

@eltank
Copy link
Contributor Author

eltank commented Jul 31, 2021

Something I noticed is that since you've implemented size-and-orientation aware A*, you've essentially also implemented pathfinding for multi-tile monsters.

The code is currently only intended to handle vehicles with a driver but yes, it can be modified to work with autonomous vehicles or multi-tile monsters. That'll actually become more feasible after I implement the "parking zone" feature, in which the code will find a path to a specific location in the current OMT rather than just going towards another OMT.

One thing that multi-tile monsters can do that vehicles can't (currently) is to rotate in place. That's something I actually want to add to the game anyway since helicopters and cars with front and back steerable wheels should be able to do this. [Edit: hmm, for cars you'd need to make some wheels drive forward while others drive in reverse which probably requires some new vpart with a high mechanics requirement]

@PatrikLundell
Copy link
Contributor

Note that normal vehicles can only use flat terrain and ramps. Monsters and mechs can use both stairs and uneven terrain (I haven't tried a mech passing over a shrub, but I'd expect it to pass "through" it, rather than smash through it), so that would be additional functionality for those use cases (of course, a piloted mech can readily restrict itself to follow vehicle rules only).
Stairs would be particularly messy with multi-tile monsters given that some maps use disjointed stair configurations, which might potentially allow them to pass one way but not return.

If you implement steering with both front and back wheels, I'd suggest the existing fly-by-wire controls to implicitly contain the computer logic for "strafe" (used for parking in real life examples) and "rotate in place" commands.
If a new vpart was introduced, I'd suggest a high Electronics rather than Mechanics (like solar panels, if I remember correctly, and you might even consider either finding a USB with control SW, and/or a high Computer skill required to "prime" the vpart)

@schealex
Copy link
Contributor

schealex commented Aug 7, 2021

I'm not sure what else needs to happen to allow this to be merged. Assuming it's held up by code reviews?

On the playtesting side, I've been using this for over a week in a non-debug playthrough using a custom build based on 0.F + various patches including this PR and it's been extremely useful in reducing keypress tedium (also, haven't had a single collision). It was very limiting without the ability to drive off-road so I made a quick hack in the overmap pathfinding code (about 20 lines), which I'm not sure whether to include in this PR or not. IMO the overmap pathfinding is buggy and inefficient so I'd like to do much more than a quick hack but obviously not in this PR.
Anyway, here's a video of offroad driving avoiding trees, critters and rocks in my debug world.

offroad1.mp4

is there something you need to toggle or activate before you can use it for offroad driving? It won't let me start autodrive unless i'm on a road and if there is no road connection to the target it will not resolve any path. Also if there is a way closer way to the target offroad it will still use the very very long way on the road instead.

Please let me know :) thanks!

BTW: This is absolutely awesome, it's helping my playthrough with a faction base setup at a big road network a lot!

@eltank
Copy link
Contributor Author

eltank commented Aug 7, 2021

is there something you need to toggle or activate before you can use it for offroad driving? It won't let me start autodrive unless i'm on a road and if there is no road connection to the target it will not resolve any path. Also if there is a way closer way to the target offroad it will still use the very very long way on the road instead.

Offroad driving is coming soon. Please subscribe to #49455 for updates.

@schealex
Copy link
Contributor

schealex commented Aug 8, 2021

Ah okay i thought it would be in this PR because of the video. Is there a branch I can test it on? Coudn't find the source branch on your fork anymore.

@eltank
Copy link
Contributor Author

eltank commented Aug 8, 2021

Ah okay i thought it would be in this PR because of the video. Is there a branch I can test it on? Coudn't find the source branch on your fork anymore.

If you're comfortable building the game from source and don't want to wait you can grab a quick hack that enables offroad driving from the "offroad_hack" branch of my fork. The final version will be much better, but I can't say when that will be ready.

eltank pushed a commit to eltank/Cataclysm-DDA that referenced this pull request Sep 3, 2021
esotericist pushed a commit to esotericist/Cataclysm-DDA that referenced this pull request Sep 4, 2021
BrettDong added a commit that referenced this pull request Nov 26, 2021
ZhilkinSerg pushed a commit that referenced this pull request Nov 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[C++] Changes (can be) made in C++. Previously named `Code` <Enhancement / Feature> New features, or enhancements on existing Quality of Life QoL: degree to which players are comfortable, and able to enjoy CDDA Vehicles Vehicles, parts, mechanics & interactions
Projects
None yet
Development

Successfully merging this pull request may close these issues.