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.cpp850
1 files changed, 0 insertions, 850 deletions
diff --git a/src/Generating/PieceGenerator.cpp b/src/Generating/PieceGenerator.cpp
deleted file mode 100644
index f8ae1d961..000000000
--- a/src/Generating/PieceGenerator.cpp
+++ /dev/null
@@ -1,850 +0,0 @@
-
-// PieceGenerator.cpp
-
-// Implements the cBFSPieceGenerator class and cDFSPieceGenerator class
-// representing base classes for generating structures composed of individual "pieces"
-
-#include "Globals.h"
-#include "PieceGenerator.h"
-#include "VerticalStrategy.h"
-#include "VerticalLimit.h"
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cPiece:
-
-bool cPiece::SetVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings)
-{
- auto strategy = CreateVerticalStrategyFromString(a_StrategyDesc, a_LogWarnings);
- if (strategy == nullptr)
- {
- return false;
- }
- m_VerticalStrategy = strategy;
- return true;
-}
-
-
-
-
-
-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;
-}
-
-
-
-
-
-Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const
-{
- Vector3i Size = GetSize();
- switch (a_NumCCWRotations)
- {
- case 0:
- {
- // No rotation needed
- return a_Pos;
- }
- case 1:
- {
- // 1 CCW rotation:
- return Vector3i(a_Pos.z, a_Pos.y, Size.x - a_Pos.x - 1);
- }
- case 2:
- {
- // 2 rotations ( = axis flip):
- return Vector3i(Size.x - a_Pos.x - 1, a_Pos.y, Size.z - a_Pos.z - 1);
- }
- case 3:
- {
- // 1 CW rotation:
- return Vector3i(Size.z - a_Pos.z - 1, a_Pos.y, a_Pos.x);
- }
- }
- ASSERT(!"Unhandled rotation");
- return a_Pos;
-}
-
-
-
-
-
-cPiece::cConnector cPiece::RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const
-{
- cPiece::cConnector res(a_Connector);
-
- // Rotate the res connector:
- switch (a_NumCCWRotations)
- {
- case 0:
- {
- // No rotation needed
- break;
- }
- case 1:
- {
- // 1 CCW rotation:
- res.m_Direction = cConnector::RotateDirectionCCW(res.m_Direction);
- break;
- }
- case 2:
- {
- // 2 rotations ( = axis flip):
- res.m_Direction = cConnector::RotateDirection(res.m_Direction);
- break;
- }
- case 3:
- {
- // 1 CW rotation:
- res.m_Direction = cConnector::RotateDirectionCW(res.m_Direction);
- break;
- }
- }
- res.m_Pos = RotatePos(a_Connector.m_Pos, a_NumCCWRotations);
-
- // Move the res connector:
- res.m_Pos.x += a_MoveX;
- res.m_Pos.y += a_MoveY;
- res.m_Pos.z += a_MoveZ;
-
- return res;
-}
-
-
-
-
-
-cCuboid cPiece::RotateHitBoxToConnector(
- const cPiece::cConnector & a_MyConnector,
- const Vector3i & a_ToConnectorPos,
- int a_NumCCWRotations
-) const
-{
- ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4));
- Vector3i ConnPos = RotatePos(a_MyConnector.m_Pos, a_NumCCWRotations);
- ConnPos = a_ToConnectorPos - ConnPos;
- return RotateMoveHitBox(a_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z);
-}
-
-
-
-
-
-cCuboid cPiece::RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const
-{
- ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4));
- cCuboid res = GetHitBox();
- res.p1 = RotatePos(res.p1, a_NumCCWRotations);
- res.p2 = RotatePos(res.p2, a_NumCCWRotations);
- res.p1.Move(a_MoveX, a_MoveY, a_MoveZ);
- res.p2.Move(a_MoveX, a_MoveY, a_MoveZ);
- return res;
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cPiece::cConnector:
-
-cPiece::cConnector::cConnector(int a_X, int a_Y, int a_Z, int a_Type, eDirection a_Direction) :
- m_Pos(a_X, a_Y, a_Z),
- m_Type(a_Type),
- m_Direction(a_Direction)
-{
-}
-
-
-
-
-
-cPiece::cConnector::cConnector(const Vector3i & a_Pos, int a_Type, eDirection a_Direction) :
- m_Pos(a_Pos),
- m_Type(a_Type),
- m_Direction(a_Direction)
-{
-}
-
-
-
-
-
-Vector3i cPiece::cConnector::AddDirection(const Vector3i & a_Pos, eDirection a_Direction)
-{
- switch (a_Direction)
- {
- case dirXM: return Vector3i(a_Pos.x - 1, a_Pos.y, a_Pos.z);
- case dirXP: return Vector3i(a_Pos.x + 1, a_Pos.y, a_Pos.z);
- case dirYM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
- case dirYP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
- case dirZM: return Vector3i(a_Pos.x, a_Pos.y, a_Pos.z - 1);
- case dirZP: return Vector3i(a_Pos.x, a_Pos.y, a_Pos.z + 1);
- case dirYM_XM_ZM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
- case dirYM_XM_ZP: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
- case dirYM_XP_ZM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
- case dirYM_XP_ZP: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
- case dirYP_XM_ZM: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
- case dirYP_XM_ZP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
- case dirYP_XP_ZM: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
- case dirYP_XP_ZP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
- }
- #if !defined(__clang__)
- ASSERT(!"Unknown connector direction");
- return a_Pos;
- #endif
-}
-
-
-
-
-
-const char * cPiece::cConnector::DirectionToString(eDirection a_Direction)
-{
- switch (a_Direction)
- {
- case dirXM: return "x-";
- case dirXP: return "x+";
- case dirYM: return "y-";
- case dirYP: return "y+";
- case dirZM: return "z-";
- case dirZP: return "z+";
- case dirYM_XM_ZM: return "y-x-z-";
- case dirYM_XM_ZP: return "y-x-z+";
- case dirYM_XP_ZM: return "y-x+z-";
- case dirYM_XP_ZP: return "y-x+z+";
- case dirYP_XM_ZM: return "y+x-z-";
- case dirYP_XM_ZP: return "y+x-z+";
- case dirYP_XP_ZM: return "y+x+z-";
- case dirYP_XP_ZP: return "y+x+z+";
- }
- #if !defined(__clang__)
- ASSERT(!"Unknown connector direction");
- return "<unknown>";
- #endif
-}
-
-
-
-
-
-bool cPiece::cConnector::IsValidDirection(int a_Direction)
-{
- switch (a_Direction)
- {
- case dirXM:
- case dirXP:
- case dirYM:
- case dirYP:
- case dirZM:
- case dirZP:
- case dirYM_XM_ZM:
- case dirYM_XM_ZP:
- case dirYM_XP_ZM:
- case dirYM_XP_ZP:
- case dirYP_XM_ZM:
- case dirYP_XM_ZP:
- case dirYP_XP_ZM:
- case dirYP_XP_ZP:
- {
- return true;
- }
- }
- return false;
-}
-
-
-
-
-
-cPiece::cConnector::eDirection cPiece::cConnector::RotateDirection(eDirection a_Direction)
-{
- // 180-degree rotation:
- switch (a_Direction)
- {
- case dirXM: return dirXP;
- case dirXP: return dirXM;
- case dirYM: return dirYM;
- case dirYP: return dirYP;
- case dirZM: return dirZM;
- case dirZP: return dirZP;
- case dirYM_XM_ZM: return dirYM_XP_ZP;
- case dirYM_XM_ZP: return dirYM_XP_ZM;
- case dirYM_XP_ZM: return dirYM_XM_ZP;
- case dirYM_XP_ZP: return dirYM_XM_ZM;
- case dirYP_XM_ZM: return dirYP_XP_ZP;
- case dirYP_XM_ZP: return dirYP_XP_ZM;
- case dirYP_XP_ZM: return dirYP_XM_ZP;
- case dirYP_XP_ZP: return dirYP_XM_ZM;
- }
- #if !defined(__clang__)
- ASSERT(!"Unknown connector direction");
- return a_Direction;
- #endif
-}
-
-
-
-
-
-cPiece::cConnector::eDirection cPiece::cConnector::RotateDirectionCCW(eDirection a_Direction)
-{
- // 90 degrees CCW rotation:
- switch (a_Direction)
- {
- case dirXM: return dirZP;
- case dirXP: return dirZM;
- case dirYM: return dirYM;
- case dirYP: return dirYP;
- case dirZM: return dirXM;
- case dirZP: return dirXP;
- case dirYM_XM_ZM: return dirYM_XM_ZP;
- case dirYM_XM_ZP: return dirYM_XP_ZP;
- case dirYM_XP_ZM: return dirYM_XM_ZM;
- case dirYM_XP_ZP: return dirYM_XP_ZM;
- case dirYP_XM_ZM: return dirYP_XM_ZP;
- case dirYP_XM_ZP: return dirYP_XP_ZP;
- case dirYP_XP_ZM: return dirYP_XM_ZM;
- case dirYP_XP_ZP: return dirYP_XP_ZM;
- }
- #if !defined(__clang__)
- ASSERT(!"Unknown connector direction");
- return a_Direction;
- #endif
-}
-
-
-
-
-
-cPiece::cConnector::eDirection cPiece::cConnector::RotateDirectionCW(eDirection a_Direction)
-{
- // 90 degrees CW rotation:
- switch (a_Direction)
- {
- case dirXM: return dirZM;
- case dirXP: return dirZP;
- case dirYM: return dirYM;
- case dirYP: return dirYP;
- case dirZM: return dirXP;
- case dirZP: return dirXM;
- case dirYM_XM_ZM: return dirYM_XP_ZM;
- case dirYM_XM_ZP: return dirYM_XM_ZM;
- case dirYM_XP_ZM: return dirYM_XP_ZP;
- case dirYM_XP_ZP: return dirYM_XM_ZP;
- case dirYP_XM_ZM: return dirYP_XP_ZM;
- case dirYP_XM_ZP: return dirYP_XM_ZM;
- case dirYP_XP_ZM: return dirYP_XP_ZP;
- case dirYP_XP_ZP: return dirYP_XM_ZP;
- }
- #if !defined(__clang__)
- ASSERT(!"Unknown connector direction");
- return a_Direction;
- #endif
-}
-
-
-
-
-
-bool cPiece::cConnector::StringToDirection(const AString & a_Value, eDirection & a_Out)
-{
- // First try converting as a number:
- int dirInt;
- if (StringToInteger(a_Value, dirInt))
- {
- if (!IsValidDirection(dirInt))
- {
- return false;
- }
- a_Out = static_cast<eDirection>(dirInt);
- return true;
- }
-
- // Compare to string representation:
- static const struct
- {
- const char * m_String;
- eDirection m_Value;
- } StringDirections[] =
- {
- {"x-", dirXM},
- {"x+", dirXP},
- {"y-", dirYM},
- {"y+", dirYP},
- {"z-", dirZM},
- {"z+", dirZP},
- {"y-x-z-", dirYM_XM_ZM},
- {"y-x-z+", dirYM_XM_ZP},
- {"y-x+z-", dirYM_XP_ZM},
- {"y-x+z+", dirYM_XP_ZP},
- {"y+x-z-", dirYP_XM_ZM},
- {"y+x-z+", dirYP_XM_ZP},
- {"y+x+z-", dirYP_XP_ZM},
- {"y+x+z+", dirYP_XP_ZP},
-
- // Alternate names, with slashes:
- {"y-/x-/z-", dirYM_XM_ZM},
- {"y-/x-/z+", dirYM_XM_ZP},
- {"y-/x+/z-", dirYM_XP_ZM},
- {"y-/x+/z+", dirYM_XP_ZP},
- {"y+/x-/z-", dirYP_XM_ZM},
- {"y+/x-/z+", dirYP_XM_ZP},
- {"y+/x+/z-", dirYP_XP_ZM},
- {"y+/x+/z+", dirYP_XP_ZP},
- };
- auto lcValue = StrToLower(a_Value);
- for (size_t i = 0; i < ARRAYCOUNT(StringDirections); i++)
- {
- if (strcmp(lcValue.c_str(), StringDirections[i].m_String) == 0)
- {
- a_Out = StringDirections[i].m_Value;
- return true;
- }
- }
-
- // Not understood, failure:
- return false;
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cPlacedPiece:
-
-cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations) :
- m_Parent(a_Parent),
- m_Piece(&a_Piece),
- m_Coords(a_Coords),
- m_NumCCWRotations(a_NumCCWRotations),
- m_HasBeenMovedToGround(false)
-{
- m_Depth = (m_Parent == nullptr) ? 0 : (m_Parent->GetDepth() + 1);
- m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z);
- m_HitBox.Sort();
-}
-
-
-
-
-
-cPiece::cConnector cPlacedPiece::GetRotatedConnector(size_t a_Index) const
-{
- cPiece::cConnectors Connectors = m_Piece->GetConnectors();
- ASSERT(Connectors.size() >= a_Index);
- return m_Piece->RotateMoveConnector(Connectors[a_Index], m_NumCCWRotations, m_Coords.x, m_Coords.y, m_Coords.z);
-}
-
-
-
-
-
-cPiece::cConnector cPlacedPiece::GetRotatedConnector(const cPiece::cConnector & a_Connector) const
-{
- return m_Piece->RotateMoveConnector(a_Connector, m_NumCCWRotations, m_Coords.x, m_Coords.y, m_Coords.z);
-}
-
-
-
-
-
-void cPlacedPiece::MoveToGroundBy(int a_OffsetY)
-{
- m_Coords.y += a_OffsetY;
- m_HasBeenMovedToGround = true;
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cPieceGenerator:
-
-cPieceGenerator::cPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) :
- m_PiecePool(a_PiecePool),
- m_Noise(a_Seed),
- m_Seed(a_Seed)
-{
-}
-
-
-
-
-
-void cPieceGenerator::FreePieces(cPlacedPieces & a_PlacedPieces)
-{
- for (cPlacedPieces::iterator itr = a_PlacedPieces.begin(), end = a_PlacedPieces.end(); itr != end; ++itr)
- {
- delete *itr;
- } // for itr - a_PlacedPieces[]
- a_PlacedPieces.clear();
-}
-
-
-
-
-
-cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockZ, cFreeConnectors & a_OutConnectors)
-{
- m_PiecePool.Reset();
- int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7;
-
- // Choose a random one of the starting pieces:
- cPieces StartingPieces = m_PiecePool.GetStartingPieces();
- int Total = 0;
- for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
- {
- Total += m_PiecePool.GetStartingPieceWeight(**itr);
- }
- cPiece * StartingPiece;
- if (Total > 0)
- {
- int Chosen = rnd % Total;
- StartingPiece = StartingPieces.front();
- for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
- {
- Chosen -= m_PiecePool.GetStartingPieceWeight(**itr);
- if (Chosen <= 0)
- {
- StartingPiece = *itr;
- break;
- }
- }
- }
- else
- {
- // All pieces returned zero weight, but we need one to start. Choose with equal chance:
- StartingPiece = StartingPieces[static_cast<size_t>(rnd) % StartingPieces.size()];
- }
- rnd = rnd >> 16;
-
- // Choose a random supported rotation:
- int Rotations[4] = {0};
- int NumRotations = 1;
- for (size_t i = 1; i < ARRAYCOUNT(Rotations); i++)
- {
- if (StartingPiece->CanRotateCCW(static_cast<int>(i)))
- {
- Rotations[NumRotations] = static_cast<int>(i);
- NumRotations += 1;
- }
- }
- int Rotation = Rotations[rnd % NumRotations];
- 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, BlockY, a_BlockZ))
- );
- }
-
- return res;
-}
-
-
-
-
-
-bool cPieceGenerator::TryPlacePieceAtConnector(
- const cPlacedPiece & a_ParentPiece,
- const cPiece::cConnector & a_Connector,
- cPlacedPieces & a_OutPieces,
- cPieceGenerator::cFreeConnectors & a_OutConnectors
-)
-{
- // Translation of direction - direction -> number of CCW rotations needed:
- // You need DirectionRotationTable[rot2][rot1] CCW turns to connect rot1 to rot2 (they are opposite)
- // -1 if not possible
- static const int DirectionRotationTable[14][14] =
- {
- /* YM, YP, ZM, ZP, XM, XP, YM-XM-ZM, YM-XM-ZP, YM-XP-ZM, YM-XP-ZP, YP-XM-ZM, YP-XM-ZP, YP-XP-ZM, YP-XP-ZP */
- /* YM */ { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- /* YP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- /* ZM */ {-1, -1, 2, 0, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1},
- /* ZP */ {-1, -1, 0, 2, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1},
- /* XM */ {-1, -1, 3, 1, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1},
- /* XP */ {-1, -1, 1, 3, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1},
- /* YM-XM-ZM */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, 1, 2},
- /* YM-XM-ZP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, 2, 3},
- /* YM-XP-ZM */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 2, 0, 1},
- /* YM-XP-ZP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 1, 3, 0},
- /* YP-XM-ZM */ {-1, -1, -1, -1, -1, -1, 0, 3, 1, 2, -1, -1, -1, -1},
- /* YP-XM-ZP */ {-1, -1, -1, -1, -1, -1, 1, 0, 2, 3, -1, -1, -1, -1},
- /* YP-XP-ZM */ {-1, -1, -1, -1, -1, -1, 3, 2, 0, 1, -1, -1, -1, -1},
- /* YP-XP-ZP */ {-1, -1, -1, -1, -1, -1, 2, 1, 3, 0, -1, -1, -1, -1},
- };
-
- // Get a list of available connections:
- ASSERT(a_Connector.m_Direction < ARRAYCOUNT(DirectionRotationTable));
- const int * RotTable = DirectionRotationTable[a_Connector.m_Direction];
- cConnections Connections;
- int WantedConnectorType = -a_Connector.m_Type;
- cPieces AvailablePieces = m_PiecePool.GetPiecesWithConnector(WantedConnectorType);
- Connections.reserve(AvailablePieces.size());
- Vector3i ConnPos = cPiece::cConnector::AddDirection(a_Connector.m_Pos, a_Connector.m_Direction); // The position at which the new connector should be placed - 1 block away from the current connector
- int WeightTotal = 0;
- for (cPieces::iterator itrP = AvailablePieces.begin(), endP = AvailablePieces.end(); itrP != endP; ++itrP)
- {
- // Get the relative chance of this piece being generated in this path:
- int Weight = m_PiecePool.GetPieceWeight(a_ParentPiece, a_Connector, **itrP);
- if (Weight <= 0)
- {
- continue;
- }
-
- // 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)
- {
- continue;
- }
- // This is a same-type connector, find out how to rotate to it:
- ASSERT(itrC->m_Direction < ARRAYCOUNT(DirectionRotationTable[0]));
- int NumCCWRotations = RotTable[itrC->m_Direction];
- if ((NumCCWRotations < 0) || !(*itrP)->CanRotateCCW(NumCCWRotations))
- {
- // 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
- continue;
- }
- // Fits, add it to list of possibile connections:
- Connections.push_back(cConnection(**itrP, *itrC, NumCCWRotations, Weight));
- WeightTotal += Weight;
- } // for itrC - Connectors[]
- } // for itrP - AvailablePieces[]
- if (Connections.empty())
- {
- // No available connections, bail out
- return false;
- }
- ASSERT(WeightTotal > 0);
-
- // Choose a random connection from the list, based on the weights:
- int rnd = (m_Noise.IntNoise3DInt(a_Connector.m_Pos.x, a_Connector.m_Pos.y, a_Connector.m_Pos.z) / 7) % WeightTotal;
- size_t ChosenIndex = 0;
- for (cConnections::const_iterator itr = Connections.begin(), end = Connections.end(); itr != end; ++itr, ++ChosenIndex)
- {
- rnd -= itr->m_Weight;
- if (rnd <= 0)
- {
- // This is the piece to choose
- break;
- }
- }
- cConnection & Conn = Connections[ChosenIndex];
-
- // Place the piece:
- Vector3i NewPos = Conn.m_Piece->RotatePos(Conn.m_Connector.m_Pos, Conn.m_NumCCWRotations);
- ConnPos -= NewPos;
- cPlacedPiece * PlacedPiece = new cPlacedPiece(&a_ParentPiece, *(Conn.m_Piece), ConnPos, Conn.m_NumCCWRotations);
- a_OutPieces.push_back(PlacedPiece);
-
- // Add the new piece's connectors to the list of free connectors:
- cPiece::cConnectors Connectors = Conn.m_Piece->GetConnectors();
- for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
- {
- if (itr->m_Pos.Equals(Conn.m_Connector.m_Pos))
- {
- // This is the connector through which we have been connected to the parent, don't add
- continue;
- }
- a_OutConnectors.push_back(cFreeConnector(PlacedPiece, Conn.m_Piece->RotateMoveConnector(*itr, Conn.m_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z)));
- }
-
- return true;
-}
-
-
-
-
-
-bool cPieceGenerator::CheckConnection(
- const cPiece::cConnector & a_ExistingConnector,
- const Vector3i & a_ToPos,
- const cPiece & a_Piece,
- const cPiece::cConnector & a_NewConnector,
- int a_NumCCWRotations,
- const cPlacedPieces & a_OutPieces
-)
-{
- // For each placed piece, test the hitbox against the new piece:
- cCuboid RotatedHitBox = a_Piece.RotateHitBoxToConnector(a_NewConnector, a_ToPos, a_NumCCWRotations);
- RotatedHitBox.Sort();
- for (cPlacedPieces::const_iterator itr = a_OutPieces.begin(), end = a_OutPieces.end(); itr != end; ++itr)
- {
- if ((*itr)->GetHitBox().DoesIntersect(RotatedHitBox))
- {
- return false;
- }
- }
- return true;
-}
-
-
-
-
-
-//*
-// DEBUG:
-void cPieceGenerator::DebugConnectorPool(const cPieceGenerator::cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed)
-{
- printf(" Connector pool: " SIZE_T_FMT " items\n", a_ConnectorPool.size() - a_NumProcessed);
- size_t idx = 0;
-
- typedef cPieceGenerator::cFreeConnectors::difference_type difType;
-
- for (auto itr = a_ConnectorPool.cbegin() + static_cast<difType>(a_NumProcessed), end = a_ConnectorPool.cend(); itr != end; ++itr, ++idx)
- {
- printf(" " SIZE_T_FMT ": {%d, %d, %d}, type %d, direction %s, depth %d\n",
- idx,
- itr->m_Connector.m_Pos.x, itr->m_Connector.m_Pos.y, itr->m_Connector.m_Pos.z,
- itr->m_Connector.m_Type,
- cPiece::cConnector::DirectionToString(itr->m_Connector.m_Direction),
- itr->m_Piece->GetDepth()
- );
- } // for itr - a_ConnectorPool[]
-}
-//*/
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cPieceGenerator::cConnection:
-
-cPieceGenerator::cConnection::cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations, int a_Weight) :
- m_Piece(&a_Piece),
- m_Connector(a_Connector),
- m_NumCCWRotations(a_NumCCWRotations),
- m_Weight(a_Weight)
-{
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cPieceGenerator::cFreeConnector:
-
-cPieceGenerator::cFreeConnector::cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector) :
- m_Piece(a_Piece),
- m_Connector(a_Connector)
-{
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cBFSPieceGenerator:
-
-cBFSPieceGenerator::cBFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) :
- super(a_PiecePool, a_Seed)
-{
-}
-
-
-
-
-
-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_BlockZ, ConnectorPool));
-
- /*
- // DEBUG:
- printf("Placed the starting piece at {%d, %d, %d}\n", a_BlockX, a_BlockY, a_BlockZ);
- cCuboid Hitbox = a_OutPieces[0]->GetHitBox();
- Hitbox.Sort();
- printf(" Hitbox: {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n",
- 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
- );
- DebugConnectorPool(ConnectorPool, 0);
- //*/
-
- // Place pieces at the available connectors:
- /*
- Instead of removing them one by one from the pool, we process them sequentially and take note of the last
- processed one. To save on memory, once the number of processed connectors reaches a big number, a chunk
- of the connectors is removed.
- */
- size_t NumProcessed = 0;
- while (ConnectorPool.size() > NumProcessed)
- {
- cFreeConnector & Conn = ConnectorPool[NumProcessed];
- if (Conn.m_Piece->GetDepth() < a_MaxDepth)
- {
- if (TryPlacePieceAtConnector(*Conn.m_Piece, Conn.m_Connector, a_OutPieces, ConnectorPool))
- {
- /*
- // DEBUG:
- const cPlacedPiece * NewPiece = a_OutPieces.back();
- const Vector3i & Coords = NewPiece->GetCoords();
- printf("Placed a new piece at {%d, %d, %d}, rotation %d\n", Coords.x, Coords.y, Coords.z, NewPiece->GetNumCCWRotations());
- cCuboid Hitbox = NewPiece->GetHitBox();
- Hitbox.Sort();
- printf(" Hitbox: {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n",
- 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
- );
- DebugConnectorPool(ConnectorPool, NumProcessed + 1);
- //*/
- }
- }
- NumProcessed++;
- if (NumProcessed > 1000)
- {
- typedef cPieceGenerator::cFreeConnectors::difference_type difType;
- ConnectorPool.erase(ConnectorPool.begin(), ConnectorPool.begin() + static_cast<difType>(NumProcessed));
- NumProcessed = 0;
- }
- }
-}
-
-
-
-