-
Notifications
You must be signed in to change notification settings - Fork 73
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
Fix bug #968 - Roads are no longer allowed to be in no-mans land or i… #1657
base: master
Are you sure you want to change the base?
Fix bug #968 - Roads are no longer allowed to be in no-mans land or i… #1657
Conversation
…n no-mans land or in border
7b3697f
to
3c24f7a
Compare
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.
Very good actually, thanks!
For completeness maybe a test for the new function (at https://github.com/Return-To-The-Roots/s25client/blob/master/tests/s25Main/simple/testMapBase.cpp) would be good. I guess just 2 hard-coded, neighbouring points, first each one separately then their union without the duplicates, again with a hard-coded list of the expected result, should be easy enough and show what is done.
It also needs recreating the test replays (the test is only run when built in release mode) because the point order is now different. See
s25client/tests/s25Main/autoplay/main.cpp
Lines 105 to 123 in fd16215
BOOST_AUTO_TEST_CASE(Play200kReplay) | |
{ | |
// Map: Big Slaughter v2 | |
// 7 x Hard KI | |
// 2 KIs each in Teams 1-3, 1 in Team 4 | |
// 200k GFs run (+ a bit) | |
const boost::filesystem::path replayPath = rttr::test::rttrBaseDir / "tests" / "testData" / "200kGFs.rpl"; | |
playReplay(replayPath); | |
} | |
BOOST_AUTO_TEST_CASE(PlaySeaReplay) | |
{ | |
// Map: Island by Island | |
// 2 x Hard KI + Player KI | |
// No teams, Sea attacks enabled, ships fast | |
// 300k GFs run (+ a bit) | |
const boost::filesystem::path replayPath = rttr::test::rttrBaseDir / "tests" / "testData" / "SeaMap300kGfs.rpl"; | |
playReplay(replayPath); | |
} |
Basically: Start the game normally with the described configuration, fast forward/skip to 200/300k GF and then copy the created replays into the test folder: https://github.com/Return-To-The-Roots/s25client/tree/fd16215cfb8b6b3cb35fb002578358d942600757/tests/testData
@Flamefire Everything except the test should be addressed. |
I see perfect thanks! Are you going to fix the test too or do you need help with that? |
i will try to add the test on my own later today or tomorow |
cc0f529
to
5d3c47e
Compare
5d3c47e
to
2d1dfbf
Compare
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.
Well done test, only a few minor improvements!
Check them and note that you can apply each suggestion from this page on Github directly without having to apply them locally.
tests/s25Main/simple/testMapBase.cpp
Outdated
auto replyEmpty = world.GetAllNeighboursUnion(testPointsEmpty); | ||
BOOST_TEST_REQUIRE(replyEmpty.empty()); | ||
|
||
// Two compontents of 1 and 2 vertices |
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.
What do "components" and "vertices" mean here? I see 3 points.
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.
Well, best explained here:
https://en.wikipedia.org/wiki/Component_(graph_theory)
https://en.wikipedia.org/wiki/Vertex_(graph_theory)
vertex is basically point
components are all connected points - two road networks in S2 are two components
can rewrite the comment to something else.
Maybe: Two sets of points
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.
I meant what you refer with "vertex" here. Because the function takes as inputs a list of points. For the purpose of this function the points are not connected, i.e. there is no vertex between (10,10) and (10,11) here, they are just neighbours. Of course you could refer to the points as nodes in a graph which basically is the map and vertices would be the relationships, i.e. what makes points neighbours. So there is a vertex between (10,10) and (10,11) but none of either to (1,1) (unless the map is small)
But I wouldn't get to technical in the comment here. So maybe:
// Two compontents of 1 and 2 vertices | |
// 3 points where the last 2 share neighbours and are neighbours to each other |
Because that is the important thing for the tested function: We get the neighbours but remove and duplicates and additionally also the points itself, but also avoid duplicates if one is the neighbour of another given point
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.
Yea, your comment works better.
// Two compontents of 1 and 2 vertices | ||
std::vector<MapPoint> testPoints{MapPoint(1, 1), MapPoint(10, 10), MapPoint(10, 11)}; | ||
// ((center + 6 connecting hexes) * 3 points in test data) - 4 common vectors for the bigger component = 17 points | ||
std::vector<MapPoint> expectedResultPoints{ |
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.
std::vector<MapPoint> expectedResultPoints{ | |
const std::vector<MapPoint> expectedResultPoints{ |
Co-authored-by: Alexander Grund <[email protected]>
Co-authored-by: Alexander Grund <[email protected]>
Co-authored-by: Alexander Grund <[email protected]>
Co-authored-by: Alexander Grund <[email protected]>
Co-authored-by: Alexander Grund <[email protected]>
Co-authored-by: Alexander Grund <[email protected]>
@Flamefire |
@@ -65,7 +65,7 @@ BOOST_FIXTURE_TEST_CASE(ProductivityStats, WorldFixtureEmpty1P) | |||
MapPoint curPos(0, 0); | |||
for(const auto bldType : helpers::EnumRange<BuildingType>{}) | |||
{ | |||
if(!BuildingProperties::IsValid(bldType)) | |||
if(!BuildingProperties::IsValid(bldType) || bldType == BuildingType::HarborBuilding) |
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.
Not sure what exactly is the failing test 'ProductivityStats' testing.
However it probably fails, because last created building Harbour is recalculating border and destroying buildings.
Just skipping the creation of harbour will fix the test
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.
That would make sense, yes. Maybe we need a comment why this is OK though:
if(!BuildingProperties::IsValid(bldType) || bldType == BuildingType::HarborBuilding) | |
if(!BuildingProperties::IsValid(bldType)) | |
continue; | |
if(bldType == BuildingType::HarborBuilding) | |
{ | |
// Creating a harbor would recalculate the territory and destroy some buildings already added in the calculation, but we don't have productivity for it so no need to test | |
BOOST_TEST_REQUIRE(!helpers::contains(iwBuildingProductivities::icons, bldType)) | |
continue | |
} |
However I don't feel so good about excluding (real) buildings here as we might miss bugs. Maybe a better solution would be to convert helpers::EnumRange<BuildingType>
into a vector and sort such that all "usual" buildings come last, i.e. BuildingProperties::IsUsual
This way territory changes only happen at the start
continue; | ||
|
||
const uint8_t owner = GetNode(curMapPt).owner; | ||
if(flag->GetPlayer() + 1 == owner && !IsBorderNode(curMapPt, owner)) |
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.
Even better (and faster):
if(flag->GetPlayer() + 1 == owner && !IsBorderNode(curMapPt, owner)) | |
if(flag->GetPlayer() + 1 == owner && IsPlayerTerritory(curMapPt, owner)) |
IsBorderNode = GetNode(pt).owner == owner && !IsPlayerTerritory(pt, owner))
--> !IsBorderNode = GetNode(pt).owner != owner || IsPlayerTerritory(pt, owner))
and the first part can never be true here
std::vector<BuildingType> buildingTypes; | ||
const auto buildingTypesEnum = helpers::EnumRange<BuildingType>{}; | ||
|
||
for(auto it = buildingTypesEnum.begin(); it != buildingTypesEnum.end(); ++it) | ||
{ | ||
buildingTypes.push_back(*it); | ||
} |
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.
We use C++11/14 so you never need this for(it=..., ++it)
but can always use the range-based-for: for(auto t: buildingTypesEnum)
However here you can just use the range constructor:
std::vector<BuildingType> buildingTypes; | |
const auto buildingTypesEnum = helpers::EnumRange<BuildingType>{}; | |
for(auto it = buildingTypesEnum.begin(); it != buildingTypesEnum.end(); ++it) | |
{ | |
buildingTypes.push_back(*it); | |
} | |
const auto buildingTypesEnum = helpers::EnumRange<BuildingType>{}; | |
std::vector<BuildingType> buildingTypes(buildingTypesEnum.begin(), buildingTypesEnum.end()); |
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.
I looked into this, and didnt manage to make it work.
believe you have to implement https://en.cppreference.com/w/cpp/iterator/iterator_tags
E0289 no instance of constructor "std::vector<_Ty, _Alloc>::vector [with _Ty=BuildingType, _Alloc=std::allocator<BuildingType>]" matches the argument list Test_integration \s25client\tests\s25Main\integration\testGamePlayer.cpp 73
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.
True. I have a PR for this #1665
Co-authored-by: Alexander Grund <[email protected]>
Fix bug #968 - Roads are no longer allowed to be in no-mans land or in border
The code is ugly so if you have any suggestions, feel free to fix it.
This should fix all problems, where roads were in places, where they shouldn't be.
If you need, I can provide few examples (savegames)