summaryrefslogtreecommitdiffstats
path: root/src/Generating/PieceGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Generating/PieceGenerator.cpp')
-rw-r--r--src/Generating/PieceGenerator.cpp173
1 files changed, 39 insertions, 134 deletions
diff --git a/src/Generating/PieceGenerator.cpp b/src/Generating/PieceGenerator.cpp
index 93e7179e2..1d58157ba 100644
--- a/src/Generating/PieceGenerator.cpp
+++ b/src/Generating/PieceGenerator.cpp
@@ -7,149 +7,46 @@
#include "Globals.h"
#include "PieceGenerator.h"
#include "../SelfTests.h"
+#include "VerticalStrategy.h"
+#include "VerticalLimit.h"
-#ifdef SELF_TEST
-
////////////////////////////////////////////////////////////////////////////////
-// Self-test:
+// cPiece:
-static class cPieceGeneratorSelfTest :
- public cPiecePool
+bool cPiece::SetVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings)
{
-public:
- cPieceGeneratorSelfTest(void)
+ auto strategy = CreateVerticalStrategyFromString(a_StrategyDesc, a_LogWarnings);
+ if (strategy == nullptr)
{
- cSelfTests::Get().Register(std::bind(&cPieceGeneratorSelfTest::Test, this), "PieceGenerator");
+ return false;
}
+ m_VerticalStrategy = strategy;
+ return true;
+}
+
+
- void Test(void)
- {
- // Prepare the internal state:
- InitializePieces();
-
- // Generate:
- cBFSPieceGenerator Gen(*this, 0);
- cPlacedPieces OutPieces;
- Gen.PlacePieces(500, 50, 500, 3, OutPieces);
-
- // Print out the pieces:
- LOG("OutPieces.size() = " SIZE_T_FMT, OutPieces.size());
- size_t idx = 0;
- for (cPlacedPieces::const_iterator itr = OutPieces.begin(), end = OutPieces.end(); itr != end; ++itr, ++idx)
- {
- const Vector3i & Coords = (*itr)->GetCoords();
- cCuboid Hitbox = (*itr)->GetHitBox();
- Hitbox.Sort();
- LOG(SIZE_T_FMT ": {%d, %d, %d}, rot %d, hitbox {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)", idx,
- Coords.x, Coords.y, Coords.z,
- (*itr)->GetNumCCWRotations(),
- Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z,
- Hitbox.p2.x, Hitbox.p2.y, Hitbox.p2.z,
- Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
- );
- } // itr - OutPieces[]
- LOG("Done.");
-
- // Free the placed pieces properly:
- Gen.FreePieces(OutPieces);
- }
-
- ~cPieceGeneratorSelfTest()
- {
- // Dealloc all the pieces:
- for (cPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
- {
- delete *itr;
- }
- m_Pieces.clear();
- }
-
-protected:
- class cTestPiece :
- public cPiece
- {
- int m_Size;
- public:
- cTestPiece(int a_Size) :
- m_Size(a_Size)
- {
- }
-
- virtual cConnectors GetConnectors(void) const override
- {
- // Each piece has 4 connectors, one of each type, plus one extra, at the center of its walls:
- cConnectors res;
- res.push_back(cConnector(m_Size / 2, 1, 0, 0, BLOCK_FACE_ZM));
- res.push_back(cConnector(m_Size / 2, 1, m_Size - 1, 1, BLOCK_FACE_ZP));
- res.push_back(cConnector(0, 1, m_Size / 2, 2, BLOCK_FACE_XM));
- res.push_back(cConnector(m_Size - 1, 1, m_Size / 2, m_Size % 3, BLOCK_FACE_XP));
- return res;
- }
-
- virtual Vector3i GetSize(void) const override
- {
- return Vector3i(m_Size, 5, m_Size);
- }
-
- virtual cCuboid GetHitBox(void) const override
- {
- return cCuboid(0, 0, 0, m_Size - 1, 4, m_Size - 1);
- }
-
- virtual bool CanRotateCCW(int a_NumCCWRotations) const override
- {
- return true;
- }
- };
-
- cPieces m_Pieces;
-
- virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override
- {
- // Each piece contains each connector
- return m_Pieces;
- }
-
-
- virtual cPieces GetStartingPieces(void) override
- {
- return m_Pieces;
- }
-
-
- virtual void PiecePlaced(const cPiece & a_Piece) override
- {
- UNUSED(a_Piece);
- }
-
-
- virtual void Reset(void) override
- {
- }
-
-
- void InitializePieces(void)
- {
- m_Pieces.push_back(new cTestPiece(5));
- m_Pieces.push_back(new cTestPiece(7));
- m_Pieces.push_back(new cTestPiece(9));
- }
-} g_Test;
-#endif // SELF_TEST
+bool cPiece::SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings)
+{
+ auto limit = CreateVerticalLimitFromString(a_LimitDesc, a_LogWarnings);
+ if (limit == nullptr)
+ {
+ return false;
+ }
+ m_VerticalLimit = limit;
+ return true;
+}
-////////////////////////////////////////////////////////////////////////////////
-// cPiece:
-
Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const
{
Vector3i Size = GetSize();
@@ -361,10 +258,10 @@ void cPieceGenerator::FreePieces(cPlacedPieces & a_PlacedPieces)
-cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, int a_BlockZ, cFreeConnectors & a_OutConnectors)
+cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockZ, cFreeConnectors & a_OutConnectors)
{
m_PiecePool.Reset();
- int rnd = m_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) / 7;
+ int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7;
// Choose a random one of the starting pieces:
cPieces StartingPieces = m_PiecePool.GetStartingPieces();
@@ -407,15 +304,17 @@ cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, i
}
}
int Rotation = Rotations[rnd % NumRotations];
-
- cPlacedPiece * res = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, a_BlockY, a_BlockZ), Rotation);
+ int BlockY = StartingPiece->GetStartingPieceHeight(a_BlockX, a_BlockZ);
+ ASSERT(BlockY >= 0); // The vertical strategy should have been provided and should give valid coords
+
+ cPlacedPiece * res = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, BlockY, a_BlockZ), Rotation);
// Place the piece's connectors into a_OutConnectors:
const cPiece::cConnectors & Conn = StartingPiece->GetConnectors();
for (cPiece::cConnectors::const_iterator itr = Conn.begin(), end = Conn.end(); itr != end; ++itr)
{
a_OutConnectors.push_back(
- cFreeConnector(res, StartingPiece->RotateMoveConnector(*itr, Rotation, a_BlockX, a_BlockY, a_BlockZ))
+ cFreeConnector(res, StartingPiece->RotateMoveConnector(*itr, Rotation, a_BlockX, BlockY, a_BlockZ))
);
}
@@ -466,6 +365,7 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
// Try fitting each of the piece's connector:
cPiece::cConnectors Connectors = (*itrP)->GetConnectors();
+ auto verticalLimit = (*itrP)->GetVerticalLimit();
for (cPiece::cConnectors::iterator itrC = Connectors.begin(), endC = Connectors.end(); itrC != endC; ++itrC)
{
if (itrC->m_Type != WantedConnectorType)
@@ -479,6 +379,13 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
// Doesn't support this rotation
continue;
}
+
+ // Check if the piece's VerticalLimit allows this connection:
+ if ((verticalLimit != nullptr) && (!verticalLimit->CanBeAtHeight(ConnPos.x, ConnPos.z, ConnPos.y - itrC->m_Pos.y)))
+ {
+ continue;
+ }
+
if (!CheckConnection(a_Connector, ConnPos, **itrP, *itrC, NumCCWRotations, a_OutPieces))
{
// Doesn't fit in this rotation
@@ -627,13 +534,13 @@ cBFSPieceGenerator::cBFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) :
-void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces)
+void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces)
{
a_OutPieces.clear();
cFreeConnectors ConnectorPool;
// Place the starting piece:
- a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockY, a_BlockZ, ConnectorPool));
+ a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockZ, ConnectorPool));
/*
// DEBUG:
@@ -681,9 +588,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
NumProcessed++;
if (NumProcessed > 1000)
{
-
typedef cPieceGenerator::cFreeConnectors::difference_type difType;
-
ConnectorPool.erase(ConnectorPool.begin(), ConnectorPool.begin() + static_cast<difType>(NumProcessed));
NumProcessed = 0;
}