Skip to content

Commit 04f18dd

Browse files
committed
Keep foresters off potential farm fields
1 parent 37e4166 commit 04f18dd

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

libs/s25main/figures/nofForester.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "nofForester.h"
66

77
#include "GameInterface.h"
8+
#include "buildings/noBaseBuilding.h"
89
#include "GamePlayer.h"
910
#include "Loader.h"
1011
#include "SoundManager.h"
@@ -15,6 +16,45 @@
1516
#include "nodeObjs/noTree.h"
1617
#include <boost/container/static_vector.hpp>
1718

19+
namespace {
20+
bool IsPotentialNewFieldForOwnFarm(GameWorld& world, const MapPoint pt, const unsigned char player)
21+
{
22+
constexpr unsigned FARM_FIELD_RADIUS = 2;
23+
24+
for(const auto dir : helpers::EnumRange<Direction>{})
25+
{
26+
if(world.GetPointRoad(pt, dir) != PointRoad::None)
27+
return false;
28+
}
29+
30+
if(!world.IsOfTerrain(pt, [](const auto& desc) { return desc.IsVital(); }))
31+
return false;
32+
33+
const NodalObjectType noType = world.GetNO(pt)->GetType();
34+
if(noType != NodalObjectType::Environment && noType != NodalObjectType::Nothing)
35+
return false;
36+
37+
for(const MapPoint nb : world.GetNeighbours(pt))
38+
{
39+
const NodalObjectType nbType = world.GetNO(nb)->GetType();
40+
if(nbType == NodalObjectType::Grainfield || nbType == NodalObjectType::Grapefield
41+
|| nbType == NodalObjectType::Building || nbType == NodalObjectType::Buildingsite)
42+
return false;
43+
}
44+
45+
return world.CheckPointsInRadius(
46+
pt, FARM_FIELD_RADIUS,
47+
[&world, player](const MapPoint farmPt, unsigned) {
48+
if(world.GetNO(farmPt)->GetType() != NodalObjectType::Building)
49+
return false;
50+
51+
const auto* building = world.GetSpecObj<noBaseBuilding>(farmPt);
52+
return building && building->GetPlayer() == player && building->GetBuildingType() == BuildingType::Farm;
53+
},
54+
false);
55+
}
56+
} // namespace
57+
1858
nofForester::nofForester(const MapPoint pos, const unsigned char player, nobUsual* workplace)
1959
: nofFarmhand(Job::Forester, pos, player, workplace)
2060
{}
@@ -110,6 +150,10 @@ nofFarmhand::PointQuality nofForester::GetPointQuality(const MapPoint pt, bool /
110150
return PointQuality::NotPossible;
111151
}
112152

153+
// Avoid occupying spots that an own farm could use for a new grain field.
154+
if(IsPotentialNewFieldForOwnFarm(*world, pt, player))
155+
return PointQuality::NotPossible;
156+
113157
// Terrain untersuchen
114158
if(world->IsOfTerrain(pt, [](const auto& desc) { return desc.IsVital(); }))
115159
return PointQuality::Class1;

tests/s25Main/integration/testFarmer.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "buildings/nobUsual.h"
77
#include "factories/BuildingFactory.h"
88
#include "figures/nofFarmhand.h"
9+
#include "figures/nofForester.h"
910
#include "worldFixtures/CreateEmptyWorld.h"
1011
#include "worldFixtures/WorldFixture.h"
1112
#include "worldFixtures/initGameRNG.hpp"
@@ -33,6 +34,29 @@ struct FarmerFixture : public WorldFixture<CreateEmptyWorld, 1>
3334
}
3435
};
3536

37+
38+
BOOST_FIXTURE_TEST_CASE(ForesterAvoidsPotentialFarmFieldSpots, FarmerFixture)
39+
{
40+
initGameRNG();
41+
42+
const auto isPointAvailable = [](const nofFarmhand* worker, const MapPoint pt) {
43+
return worker->GetPointQuality(pt) != nofFarmhand::PointQuality::NotPossible;
44+
};
45+
46+
const MapPoint fieldPt = world.GetNeighbour2(farmPt, 0);
47+
BOOST_TEST_REQUIRE(isPointAvailable(farmer, fieldPt));
48+
49+
const MapPoint foresterPt = world.MakeMapPoint(world.GetPlayer(0).GetHQPos() - Position(5, 0));
50+
auto* foresterBuilding = dynamic_cast<nobUsual*>(
51+
BuildingFactory::CreateBuilding(world, BuildingType::Forester, foresterPt, 0, Nation::Romans));
52+
BOOST_TEST_REQUIRE(foresterBuilding);
53+
54+
nofForester foresterWorker(world.GetNeighbour(foresterPt, Direction::SouthEast), 0, foresterBuilding);
55+
const nofFarmhand* forester = &foresterWorker;
56+
57+
BOOST_TEST_REQUIRE(!isPointAvailable(forester, fieldPt));
58+
}
59+
3660
BOOST_FIXTURE_TEST_CASE(FarmFieldPlanting, FarmerFixture)
3761
{
3862
initGameRNG();

0 commit comments

Comments
 (0)