Skip to content

Commit 3f214f7

Browse files
committed
Keep foresters off potential farm fields
1 parent 37e4166 commit 3f214f7

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

libs/s25main/figures/nofForester.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,53 @@
88
#include "GamePlayer.h"
99
#include "Loader.h"
1010
#include "SoundManager.h"
11+
#include "buildings/noBaseBuilding.h"
1112
#include "network/GameClient.h"
1213
#include "ogl/glArchivItem_Bitmap_Player.h"
1314
#include "random/Random.h"
1415
#include "world/GameWorld.h"
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: 23 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,28 @@ struct FarmerFixture : public WorldFixture<CreateEmptyWorld, 1>
3334
}
3435
};
3536

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

0 commit comments

Comments
 (0)