1
DF Dwarf Mode Discussion / Re: FPS Science and observations with 1000 dorfs population
« on: April 25, 2023, 05:03:44 am »
There's no point suggesting improvements evidently so I won't waste my time anymore, have fun.
March 6, 2024: Dwarf Fortress 50.12 has been released.
News: February 3, 2024: The February '24 Report is up.
News: February 4, 2021: Dwarf Fortress Talk #28 has been posted.
News: November 21, 2018: A new Threetoe story has been posted.
Forum Guidelines
It's not storing the information because that information becomes useless the next frame.
"Storing information about which units are nearby" is fundamentally equivalent to figuring it out by doing a nested loop. This is collision detection, and a lot of the optimizations requires various assumptions that we simply do not have the ability to consume. In fact, we're already doing one of the biggest optimizations, an axis-aligned bounding box, checking if the other object is within a 53x53x53 AABB with its center at the dwarf. This is a known problem, it's not like I haven't done research into all this.It's not storing the information though is it, because every frame the information about which units can see each other is dropped and has to be regenerated from scratch; every calculation about every pair of units has to be done again, in both directions.
You'll find that the vast majority of the optimizations there contain such phrases as "Where most of the objects involved are fixed" or "that approach is well suited to handling walls and fixed obstacles in games". Dwarf Fortress doesn't have those, so a lot of the optimizations would be costly to implement in the first place. You can't "pre-bake" stuff into a map that changes all the time.
Yeah, unfortunately, that "most" happens to not include dwarves, who can see further underground than most, and also doesn't include goblins, who can be seen further underground than most.I still don't see the problem, since dwarves looking at dwarves will have the same stats, which is going to be the most common comparison by far. Even if the two units have different sight characteristics, if you are lucky (50% of the time) you'll get the unit with shorter sight of the pair first and not have to check LoS the other way.
Storing information about which units are nearby is fundamentally going to be faster than figuring it out every frame by doing a nested loop over all the units, regardless of whether the current structure of the game sucks.Maybe there should be a data structure that stores information about the location of things in the map then?
The way the game is structured is already a nightmare for the cache, which is the actual largest cause of performance issues; just improving cache locality on units a little improved performance by 60%, yet more big ol' structures isn't going to help; moving unit positions out into their own array is likely to be the biggest gain, funnily enough
Creatures keep track of their own positions, there's no concept of "checking tiles in the vicinity" except checking every unit to see if they're nearby, these are synonymous with the way the game is structured
Edit: Possibly in the current way you could reduce some of the work by saying if dwarf A has line of sight to B on this tick, assume B has line of sight to A unless he has different sight distance. Yay still waking up. I think this would reduce the number of checks you have to do by about half, assuming most units have the same sight distance.
Also, maybe you could defer LoS checks for pairs of nearby creatures that you just checked - If I had LoS to you last tick, and we're still more or less in the same room, don't check LoS again.
Can't, low-light vision and glowtiles means that A sees B does not imply B sees A
I think the "stand there while a dragon is breathing fire at them" example wasn't an issue with not checking the tile they're standing on frequently enough for environmental hazards, but identifying that there's even a dragon there in the first place that they should be concerned about. Checking for "tiles currently the target of a hostile action" doesn't solve the issue of fleeing from the dragon in the first place, which was the main point.With the dragon, you could still know a dragon is around reasonably well if you check LoS every say, 2, 3, or even 5 ticks. And by combining that with the check i mentioned where you have a hostile action even if some really fast creature manages to gap close too fast, you can respond to the attack itself.
As for breaking up the whole thing into a grid, that doesn't work nearly as well as it sounds due to the joys of the million-odd edge and corner (literally) cases. That and maintaining such a large structure and having to shuffle around which units are in which box, more often than not, will be more expensive than just checking against every other unit on the map, doing a quick "is it 26 units away?" distance check, and if not, then doing a line-of-sight check.
The game is, from a technical standpoint, sparse. Very large map, very few units. There are times where there are a lot of units (sieges, namely), but we're still talking a drop in the bucket compared to the size of a map (tile-wise a map is about 100 levels tall and hundreds of tiles across). Subdividing the search space only makes sense from an optimization standpoint for dense, not sparse, situations, usually (caveats always apply of course).
They happen every time dwarves are able to act and they need to happen every time dwarves are able to act, otherwise they will not react properly to their environment and will just stand there while a dragon is breathing fire at them et cetera.Might it be cheaper to check the immediate tiles in your vicinity for danger rather than looping through every unit in the game to see if they're nearby?
The game already splits accessibility into subregions, that's kinda the problem. Having more subregion maps for pets, flying units etc. would be a performance disaster, nevermind everything else.Regions but not subregions. https://youtu.be/RMBQn_sg7DA?t=1035 Have a watch of the whole thing it's pretty cool.
You can do O(1) existence lookups, like say a hash table of creatures in the fortSure, why don't you get right on that.
You can do O(1) existence lookups, like say a hash table of creatures in the fortA dwarf will never meet their grandfather in your fort if their grandfather is not in the fort.How else are they supposed to know if their grandfather is in the fort?
I did another 3-minute profile on my 260-citizen fort, this time with the knowledge of the source. Percents are going to overlap some. Specific seconds are not.
The slowest thing was line-of-sight checks. Due to the fact that it was only counting the checks in the function itself, this was a total of 14.7% of CPU time. However, if you remove one specific thing from line-of-sight checks (more on that later), it's 8%, and thus faster than the next thing. 13.181s in the function itself.
The slowest individual thing in the fort was checking family relationships. This was mostly, so far as I could tell, called in the context of watching performances, probably to tell if they should be feeling love at their family members or whatever. This was 9% of CPU time. 15.537 in the function.
Next is getting glowtiles. This is required for line-of-sight tests, naturally. Glowtile'd creatures are visible from farther in the dark. 5.7%. This is the slowest part of line-of-sight checks, at least as far as stuff that's actually done. 11.749s.