-
Notifications
You must be signed in to change notification settings - Fork 278
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
Smoother rivers connections on overmaps edges #3178
Conversation
Worth porting back to CDDA itself <3 |
@Zireael07 hi, thanks for the interest in our project. however, as this is BN repository and not DDA repository, could you open a feature request on DDA issues instead? you could mention the PR you want to port via leaving a url on DDA issue, such as: https://github.com/cataclysmbnteam/Cataclysm-BN/pull/3178 and it would link to this PR automatically. |
I know, however many of BN contributors are also DDA contributors and often will open PRs themselves. (Opening a PR necessitates you test the changes, which means you need the ability to compile from source) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MacOS build timed out, but that was most likely unrelated.
if( ( x > 0 && y > 0 && | ||
!is_river_or_lake( ter( { x - 1, y - 1, 0} ) ) ) || | ||
( x > 0 && y == 0 && north != nullptr && | ||
!is_river_or_lake( north->ter( { x - 1, OMAPY - 1, 0} ) ) ) || | ||
( x == 0 && y > 0 && west != nullptr && | ||
!is_river_or_lake( west->ter( { OMAPX - 1, y - 1, 0} ) ) ) | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an easy way to extract these checks into some function, or closure, that would take x
and y
and decide for which of the 5 overmaps, and at what point, to call the ter
method?
continue; | ||
} | ||
|
||
// For ungenerated overmaps we're assuming that terra incognita is covered by water, and leaving polishing to its mapgen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything from this line and to the end of the loop should really be extracted into a separate function.
good_river
was a terrible name, but something like polish_river_tile(x,y,north,south,east,west)
simply begs to exist here.
Usually the less nested if
s and for
s there are in a function, the more readable it is.
om_dir get_dir(point p) { //Enum declaration skipped
if (p.x < 0) {
if (p.y < 0) {
return DIR_NORTHWEST;
} else if (p.y > OMAPY - 1) {
return DIR_SOUTHWEST;
} else {
return DIR_WEST;
}
} else if (p.x > OMAPX - 1) {
if (p.y < 0) {
return DIR_NORTHEAST;
} else if (p.y > OMAPY - 1) {
return DIR_SOUTHEAST;
} else {
return DIR_EAST;
}
} else if (p.y < 0) {
return DIR_NORTH;
} else if (p.y > OMAPY - 1) {
return DIR_SOUTH;
} else {
return DIR_HERE;
}
}
void shift_pos(point p) {
if (p.x < 0) {
p.x = OMAPX - 1 + p.x;
} else if (p.x > OMAPX - 1) {
p.x = p.x - OMAPX - 1;
}
if (p.y < 0) {
p.y = OMAPY - 1 + p.y;
} else if (p.y > OMAPY - 1) {
p.y = p.y - OMAPY - 1;
}
}
bool is_corner_needed(overmap o, point p) {
return o !== nullptr && !is_river_or_lake( o->ter( p ) );
}
...
overmap* om[DIR_MAX] = { nullptr };
om[DIR_NORTHEAST] = nullptr; // Diagonal overmaps lookup *could* be useful, if they'd be already loaded. Since they're not - it doesn't worth the hassle.
om[DIR_NORTH] = north;
om[DIR_HERE] = this;
...
if ( is_corner_needed(om[get_dir(p + point_north_east)], shift_pos(p + point_north_east)) ) {
ter_set( p, oter_id( "river_c_not_ne" ) );
} Everything can be refactored. Like to this monstrosity. But it doesn't seems much better to me - two screens of code scattered around where few lines of checks could do the work. Those checks looks ugly, i admit that, but they're trivial and basically same. After spending 5 seconds looking at first one you can tell immediately what all the other ones does. And it's write once code anyway, not something that will need to be tweaked further. (Unless i screwed offsets somewhere ofc, but it won't take a long to notice and fix)
Getting rid of |
There's a lot to debate when it comes to abstractions, code reuse, reliability, readability and performance, but I can agree that it is unlikely anyone will touch this code for years to come, and it's out of the way, so these topics don't matter much for this case or warrant holding up the PR over. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing this bug, it's been around since forever.
It is indeed very debatable topic. I really don't feel good about deliberate degrading of performance without solid reason. In my world ugly code is better than slow code :) I might be unreasonable too strict about such things, so feel free to insist when you feel it does matter. I'm not stubbornly refusing - just wanted to explain my reasoning, and ask for confirmation - whether i really should do it. Anyway, glad it's settled down. |
Summary
SUMMARY: Bugfixes "Smoother rivers connections on overmaps edges"
Purpose of change
River connections and side touches are often generated with cut edge next to overmap border, without any shore. This change polish all those edges.
Describe the solution
River polishing function will now be aware of adjacent tiles even if they're on different overmap, so it knows where shores should be placed. For not yet generated overmaps it assumes that water continues as it goes, leaving polishing to their mapgens, which can handle that nicely.
Describe alternatives you've considered
Rewriting
overmap::place_river
to make starting points of rivers always match each others, and never touch borders in any other places.Testing
Jumped between overmaps in debug mode, following river. Looks much better now.
Additional context
It's a bit difficult to show the difference due to map randomness, but that should give an idea what it does on pretty similar layouts.
Overmap edge, before fix, and after fix: