From 187abe3f5e2219e0a80c0cdca4db362e223b60ae Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 26 Feb 2017 22:49:23 +0100 Subject: Gen: Moved PiecePool into a separate file. Also rewritten the PieceGenerator to use std::unique_ptr. --- src/Generating/PieceGenerator.cpp | 850 -------------------------------------- 1 file changed, 850 deletions(-) delete mode 100644 src/Generating/PieceGenerator.cpp (limited to 'src/Generating/PieceGenerator.cpp') 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 ""; - #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(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(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(i))) - { - Rotations[NumRotations] = static_cast(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(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(NumProcessed)); - NumProcessed = 0; - } - } -} - - - - -- cgit v1.2.3