summaryrefslogtreecommitdiffstats
path: root/src/Generating
diff options
context:
space:
mode:
Diffstat (limited to 'src/Generating')
-rw-r--r--src/Generating/Caves.h2
-rw-r--r--src/Generating/GridStructGen.cpp138
-rw-r--r--src/Generating/GridStructGen.h124
-rw-r--r--src/Generating/NetherFortGen.cpp223
-rw-r--r--src/Generating/NetherFortGen.h61
-rw-r--r--src/Generating/PrefabPiecePool.cpp121
-rw-r--r--src/Generating/PrefabPiecePool.h79
7 files changed, 492 insertions, 256 deletions
diff --git a/src/Generating/Caves.h b/src/Generating/Caves.h
index 7c45c056b..2a9fa01b8 100644
--- a/src/Generating/Caves.h
+++ b/src/Generating/Caves.h
@@ -93,7 +93,7 @@ protected:
/// Returns all caves that *may* intersect the given chunk. All the caves are valid until the next call to this function.
void GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cCaveSystems & a_Caves);
- // cStructGen override:
+ // cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;
diff --git a/src/Generating/GridStructGen.cpp b/src/Generating/GridStructGen.cpp
new file mode 100644
index 000000000..2f064d3a0
--- /dev/null
+++ b/src/Generating/GridStructGen.cpp
@@ -0,0 +1,138 @@
+
+// GridStructGen.cpp
+
+// Implements the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid
+
+#include "Globals.h"
+#include "GridStructGen.h"
+
+
+
+
+cGridStructGen::cGridStructGen(
+ int a_Seed,
+ int a_GridSizeX, int a_GridSizeZ,
+ int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
+ size_t a_MaxCacheSize
+) :
+ m_Seed(a_Seed),
+ m_GridSizeX(a_GridSizeX),
+ m_GridSizeZ(a_GridSizeZ),
+ m_MaxStructureSizeX(a_MaxStructureSizeX),
+ m_MaxStructureSizeZ(a_MaxStructureSizeZ),
+ m_MaxCacheSize(a_MaxCacheSize)
+{
+}
+
+
+
+
+
+void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures)
+{
+ // Calculate the min and max grid coords of the structures to be returned:
+ int MinBlockX = a_ChunkX * cChunkDef::Width - m_MaxStructureSizeX;
+ int MinBlockZ = a_ChunkZ * cChunkDef::Width - m_MaxStructureSizeZ;
+ int MaxBlockX = a_ChunkX * cChunkDef::Width + m_MaxStructureSizeX + cChunkDef::Width - 1;
+ int MaxBlockZ = a_ChunkZ * cChunkDef::Width + m_MaxStructureSizeZ + cChunkDef::Width - 1;
+ int MinGridX = MinBlockX / m_GridSizeX;
+ int MinGridZ = MinBlockZ / m_GridSizeZ;
+ int MaxGridX = (MaxBlockX + m_GridSizeX - 1) / m_GridSizeX;
+ int MaxGridZ = (MaxBlockZ + m_GridSizeZ - 1) / m_GridSizeZ;
+ if (MinBlockX < 0)
+ {
+ --MinGridX;
+ }
+ if (MinBlockZ < 0)
+ {
+ --MinGridZ;
+ }
+ if (MaxBlockX < 0)
+ {
+ --MaxGridX;
+ }
+ if (MaxBlockZ < 0)
+ {
+ --MaxGridZ;
+ }
+
+ // Walk the cache, move each structure that we want into a_Structures:
+ for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
+ {
+ if (
+ ((*itr)->m_OriginX >= MinBlockX) && ((*itr)->m_OriginX < MaxBlockX) &&
+ ((*itr)->m_OriginZ >= MinBlockZ) && ((*itr)->m_OriginZ < MaxBlockZ)
+ )
+ {
+ // want
+ a_Structures.push_back(*itr);
+ itr = m_Cache.erase(itr);
+ }
+ else
+ {
+ // don't want
+ ++itr;
+ }
+ } // for itr - m_Cache[]
+
+ // Create those structures that haven't been in the cache:
+ for (int x = MinGridX; x < MaxGridX; x++)
+ {
+ int OriginX = x * m_GridSizeX;
+ for (int z = MinGridZ; z < MaxGridZ; z++)
+ {
+ int OriginZ = z * m_GridSizeZ;
+ bool Found = false;
+ for (cStructurePtrs::const_iterator itr = a_Structures.begin(), end = a_Structures.end(); itr != end; ++itr)
+ {
+ if (((*itr)->m_OriginX == OriginX) && ((*itr)->m_OriginZ == OriginZ))
+ {
+ Found = true;
+ break;
+ }
+ } // for itr - a_Structures[]
+ if (!Found)
+ {
+ a_Structures.push_back(CreateStructure(OriginX, OriginZ));
+ }
+ } // for z
+ } // for x
+
+ // Copy a_Forts into m_Cache to the beginning:
+ cStructurePtrs StructuresCopy (a_Structures);
+ m_Cache.splice(m_Cache.begin(), StructuresCopy, StructuresCopy.begin(), StructuresCopy.end());
+
+ // Trim the cache if it's too long:
+ size_t CacheSize = 0;
+ for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
+ {
+ CacheSize += (*itr)->GetCacheCost();
+ if (CacheSize > m_MaxCacheSize)
+ {
+ // Erase all items from this one till the cache end
+ m_Cache.erase(itr, m_Cache.end());
+ break;
+ }
+ }
+}
+
+
+
+
+
+void cGridStructGen::GenFinish(cChunkDesc & a_ChunkDesc)
+{
+ int ChunkX = a_ChunkDesc.GetChunkX();
+ int ChunkZ = a_ChunkDesc.GetChunkZ();
+ cStructurePtrs Structures;
+ GetStructuresForChunk(ChunkX, ChunkZ, Structures);
+ for (cStructurePtrs::const_iterator itr = Structures.begin(); itr != Structures.end(); ++itr)
+ {
+ (*itr)->DrawIntoChunk(a_ChunkDesc);
+ } // for itr - Structures[]
+}
+
+
+
+
+
diff --git a/src/Generating/GridStructGen.h b/src/Generating/GridStructGen.h
new file mode 100644
index 000000000..234cc75c5
--- /dev/null
+++ b/src/Generating/GridStructGen.h
@@ -0,0 +1,124 @@
+
+// GridStructGen.h
+
+// Declares the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid
+
+
+
+
+
+#pragma once
+
+#include "ComposableGenerator.h"
+
+
+
+
+
+/** Generates structures in a semi-random grid.
+Defines a grid in the XZ space with predefined cell size in each direction. Each cell then receives exactly
+one structure (provided by the descendant class). The structure is placed within the cell, but doesn't need
+to be bounded by the cell, it can be well outside the cell; the generator uses the MaxStructureSize parameter
+to determine how far away from the cell the structure can be at most.
+This class provides a cache for the structures generated for successive chunks and manages that cache. It
+also provides the cFinishGen override that uses the cache to actually generate the structure into chunk data.
+
+After generating each chunk the cache is checked for size, each item in the cache has a cost associated with
+it and the cache is trimmed (from its least-recently-used end) so that the sum of the cost in the cache is
+less than m_MaxCacheSize
+
+To use this class, declare a descendant class that implements the overridable methods, then create an
+instance of that class. The descendant must provide the CreateStructure() function that is called to generate
+a structure at the specific grid cell.
+
+The descendant must use a specific cStructure descendant to provide the actual structure that gets generated.
+The structure must provide the DrawIntoChunk() function that generates the structure into the chunk data, and
+can override the GetCacheCost() function that returns the cost of that structure in the cache.
+*/
+class cGridStructGen :
+ public cFinishGen
+{
+public:
+ cGridStructGen(
+ int a_Seed,
+ int a_GridSizeX, int a_GridSizeZ,
+ int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
+ size_t a_MaxCacheSize
+ );
+
+protected:
+ /** Represents a single structure that occupies the grid point. Knows how to draw itself into a chunk. */
+ class cStructure
+ {
+ public:
+ /** The origin (the coords of the gridpoint for which the structure is generated) */
+ int m_OriginX, m_OriginZ;
+
+
+ /** Creates a structure that has its originset at the specified coords. */
+ cStructure (int a_OriginX, int a_OriginZ) :
+ m_OriginX(a_OriginX),
+ m_OriginZ(a_OriginZ)
+ {
+ }
+
+ // Force a virtual destructor in descendants:
+ virtual ~cStructure() {}
+
+ /** Draws self into the specified chunk */
+ virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) = 0;
+
+ /** Returns the cost of keeping this structure in the cache */
+ virtual size_t GetCacheCost(void) const { return 1; }
+ } ;
+ typedef SharedPtr<cStructure> cStructurePtr;
+ typedef std::list<cStructurePtr> cStructurePtrs;
+
+
+ /** Seed for generating the semi-random grid. */
+ int m_Seed;
+
+ /** The size of each grid's cell in the X axis */
+ int m_GridSizeX;
+
+ /** The size of each grid's cell in the Z axis */
+ int m_GridSizeZ;
+
+ /** Maximum theoretical size of the structure in the X axis.
+ This limits the structures considered for a single chunk, so the lesser the number, the better performance.
+ Structures large than this may get cropped. */
+ int m_MaxStructureSizeX;
+
+ /** Maximum theoretical size of the structure in the Z axis.
+ This limits the structures considered for a single chunk, so the lesser the number, the better performance.
+ Structures large than this may get cropped. */
+ int m_MaxStructureSizeZ;
+
+ /** Maximum allowed sum of costs for items in the cache. Items that are over this cost are removed from the
+ cache, oldest-first */
+ size_t m_MaxCacheSize;
+
+ /** Cache for the most recently generated structures, ordered by the recentness. */
+ cStructurePtrs m_Cache;
+
+
+ /** Clears everything from the cache */
+ void ClearCache(void);
+
+ /** Returns all structures that may intersect the given chunk.
+ The structures are considered as intersecting iff their bounding box (defined by m_MaxStructureSize)
+ around their gridpoint intersects the chunk. */
+ void GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures);
+
+ // cFinishGen overrides:
+ virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
+
+ // Functions for the descendants to override:
+ /** Create a new structure at the specified gridpoint */
+ virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) = 0;
+} ;
+
+
+
+
+
diff --git a/src/Generating/NetherFortGen.cpp b/src/Generating/NetherFortGen.cpp
index d90fdeb0a..ac7fd0b7b 100644
--- a/src/Generating/NetherFortGen.cpp
+++ b/src/Generating/NetherFortGen.cpp
@@ -20,20 +20,21 @@ static const int NEIGHBORHOOD_SIZE = 3;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cNetherFortGen::cNetherFort:
-class cNetherFortGen::cNetherFort
+class cNetherFortGen::cNetherFort :
+ public cGridStructGen::cStructure
{
+ typedef cGridStructGen::cStructure super;
+
public:
cNetherFortGen & m_ParentGen;
- int m_BlockX, m_BlockZ;
int m_GridSize;
int m_Seed;
cPlacedPieces m_Pieces;
- cNetherFort(cNetherFortGen & a_ParentGen, int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
+ cNetherFort(cNetherFortGen & a_ParentGen, int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
+ super(a_OriginX, a_OriginZ),
m_ParentGen(a_ParentGen),
- m_BlockX(a_BlockX),
- m_BlockZ(a_BlockZ),
m_GridSize(a_GridSize),
m_Seed(a_Seed)
{
@@ -43,8 +44,8 @@ public:
// Generate pieces:
for (int i = 0; m_Pieces.size() < (size_t)(a_MaxDepth * a_MaxDepth / 8 + a_MaxDepth); i++)
{
- cBFSPieceGenerator pg(m_ParentGen, a_Seed + i);
- pg.PlacePieces(a_BlockX, BlockY, a_BlockZ, a_MaxDepth, m_Pieces);
+ cBFSPieceGenerator pg(cNetherFortGen::m_PiecePool, a_Seed + i);
+ pg.PlacePieces(a_OriginX, BlockY, a_OriginZ, a_MaxDepth, m_Pieces);
}
}
@@ -56,7 +57,7 @@ public:
/** Carves the system into the chunk data */
- void ProcessChunk(cChunkDesc & a_Chunk)
+ virtual void DrawIntoChunk(cChunkDesc & a_Chunk)
{
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
@@ -107,214 +108,30 @@ public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cNetherFortGen:
+cPrefabPiecePool cNetherFortGen::m_PiecePool(g_NetherFortPrefabs, g_NetherFortPrefabsCount, g_NetherFortStartingPrefabs, g_NetherFortStartingPrefabsCount);
+
+
+
+
+
cNetherFortGen::cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth) :
- m_Seed(a_Seed),
- m_Noise(a_Seed),
- m_GridSize(a_GridSize),
+ super(a_Seed, a_GridSize, a_GridSize, a_MaxDepth * 10, a_MaxDepth * 10, 200),
m_MaxDepth(a_MaxDepth)
{
- // Initialize the prefabs:
- for (size_t i = 0; i < g_NetherFortPrefabsCount; i++)
- {
- cPrefab * Prefab = new cPrefab(g_NetherFortPrefabs[i]);
- m_AllPieces.push_back(Prefab);
- if (Prefab->HasConnectorType(0))
- {
- m_OuterPieces.push_back(Prefab);
- }
- if (Prefab->HasConnectorType(1))
- {
- m_InnerPieces.push_back(Prefab);
- }
- }
-
- // Initialize the starting piece prefabs:
- for (size_t i = 0; i < g_NetherFortStartingPrefabsCount; i++)
- {
- m_StartingPieces.push_back(new cPrefab(g_NetherFortStartingPrefabs[i]));
- }
-
/*
// DEBUG: Try one round of placement:
cPlacedPieces Pieces;
- cBFSPieceGenerator pg(*this, a_Seed);
+ cBFSPieceGenerator pg(m_PiecePool, a_Seed);
pg.PlacePieces(0, 64, 0, a_MaxDepth, Pieces);
- */
-}
-
-
-
-
-
-cNetherFortGen::~cNetherFortGen()
-{
- ClearCache();
- for (cPieces::iterator itr = m_AllPieces.begin(), end = m_AllPieces.end(); itr != end; ++itr)
- {
- delete *itr;
- } // for itr - m_AllPieces[]
- m_AllPieces.clear();
+ //*/
}
-void cNetherFortGen::ClearCache(void)
+cGridStructGen::cStructurePtr cNetherFortGen::CreateStructure(int a_OriginX, int a_OriginZ)
{
- // TODO
+ return cStructurePtr(new cNetherFort(*this, a_OriginX, a_OriginZ, m_GridSizeX, m_MaxDepth, m_Seed));
}
-
-
-
-
-void cNetherFortGen::GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts)
-{
- int BaseX = a_ChunkX * cChunkDef::Width / m_GridSize;
- int BaseZ = a_ChunkZ * cChunkDef::Width / m_GridSize;
- if (BaseX < 0)
- {
- --BaseX;
- }
- if (BaseZ < 0)
- {
- --BaseZ;
- }
- BaseX -= NEIGHBORHOOD_SIZE / 2;
- BaseZ -= NEIGHBORHOOD_SIZE / 2;
-
- // Walk the cache, move each cave system that we want into a_Forts:
- int StartX = BaseX * m_GridSize;
- int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
- int StartZ = BaseZ * m_GridSize;
- int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
- for (cNetherForts::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
- {
- if (
- ((*itr)->m_BlockX >= StartX) && ((*itr)->m_BlockX < EndX) &&
- ((*itr)->m_BlockZ >= StartZ) && ((*itr)->m_BlockZ < EndZ)
- )
- {
- // want
- a_Forts.push_back(*itr);
- itr = m_Cache.erase(itr);
- }
- else
- {
- // don't want
- ++itr;
- }
- } // for itr - m_Cache[]
-
- // Create those forts that haven't been in the cache:
- for (int x = 0; x < NEIGHBORHOOD_SIZE; x++)
- {
- int RealX = (BaseX + x) * m_GridSize;
- for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
- {
- int RealZ = (BaseZ + z) * m_GridSize;
- bool Found = false;
- for (cNetherForts::const_iterator itr = a_Forts.begin(), end = a_Forts.end(); itr != end; ++itr)
- {
- if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
- {
- Found = true;
- break;
- }
- } // for itr - a_Mineshafts
- if (!Found)
- {
- a_Forts.push_back(new cNetherFort(*this, RealX, RealZ, m_GridSize, m_MaxDepth, m_Seed));
- }
- } // for z
- } // for x
-
- // Copy a_Forts into m_Cache to the beginning:
- cNetherForts FortsCopy (a_Forts);
- m_Cache.splice(m_Cache.begin(), FortsCopy, FortsCopy.begin(), FortsCopy.end());
-
- // Trim the cache if it's too long:
- if (m_Cache.size() > 100)
- {
- cNetherForts::iterator itr = m_Cache.begin();
- std::advance(itr, 100);
- for (cNetherForts::iterator end = m_Cache.end(); itr != end; ++itr)
- {
- delete *itr;
- }
- itr = m_Cache.begin();
- std::advance(itr, 100);
- m_Cache.erase(itr, m_Cache.end());
- }
-}
-
-
-
-
-
-void cNetherFortGen::GenFinish(cChunkDesc & a_ChunkDesc)
-{
- int ChunkX = a_ChunkDesc.GetChunkX();
- int ChunkZ = a_ChunkDesc.GetChunkZ();
- cNetherForts Forts;
- GetFortsForChunk(ChunkX, ChunkZ, Forts);
- for (cNetherForts::const_iterator itr = Forts.begin(); itr != Forts.end(); ++itr)
- {
- (*itr)->ProcessChunk(a_ChunkDesc);
- } // for itr - Forts[]
-}
-
-
-
-
-
-cPieces cNetherFortGen::GetPiecesWithConnector(int a_ConnectorType)
-{
- switch (a_ConnectorType)
- {
- case 0: return m_OuterPieces;
- case 1: return m_InnerPieces;
- default: return cPieces();
- }
-}
-
-
-
-
-
-cPieces cNetherFortGen::GetStartingPieces(void)
-{
- return m_StartingPieces;
-}
-
-
-
-
-
-int cNetherFortGen::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
-{
- return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
-}
-
-
-
-
-
-void cNetherFortGen::PiecePlaced(const cPiece & a_Piece)
-{
- UNUSED(a_Piece);
-}
-
-
-
-
-
-void cNetherFortGen::Reset(void)
-{
- // Nothing needed
-}
-
-
-
-
diff --git a/src/Generating/NetherFortGen.h b/src/Generating/NetherFortGen.h
index d51596b9e..f35801a3c 100644
--- a/src/Generating/NetherFortGen.h
+++ b/src/Generating/NetherFortGen.h
@@ -10,77 +10,34 @@
#pragma once
#include "ComposableGenerator.h"
-#include "PieceGenerator.h"
+#include "PrefabPiecePool.h"
+#include "GridStructGen.h"
class cNetherFortGen :
- public cFinishGen,
- public cPiecePool
+ public cGridStructGen
{
+ typedef cGridStructGen super;
+
public:
cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth);
- virtual ~cNetherFortGen();
-
protected:
friend class cNetherFortPerfTest; // fwd: NetherFortGen.cpp
class cNetherFort; // fwd: NetherFortGen.cpp
- typedef std::list<cNetherFort *> cNetherForts;
-
-
- /** The seed used for generating*/
- int m_Seed;
-
- /** The noise used for generating */
- cNoise m_Noise;
-
- /** Average spacing between the fortresses*/
- int m_GridSize;
/** Maximum depth of the piece-generator tree */
int m_MaxDepth;
-
- /** Cache of the most recently used systems. MoveToFront used. */
- cNetherForts m_Cache;
- /** All the pieces that are allowed for building.
- This is the list that's used for memory allocation and deallocation for the pieces. */
- cPieces m_AllPieces;
+ /** The pool of pieces to use for generating. Static, so that it's shared by multiple generators. */
+ static cPrefabPiecePool m_PiecePool;
- /** The pieces that are used as starting pieces.
- This list is not shared and the pieces need deallocation. */
- cPieces m_StartingPieces;
-
- /** The pieces that have an "outer" connector.
- The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
- cPieces m_OuterPieces;
-
- /** The pieces that have an "inner" connector.
- The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
- cPieces m_InnerPieces;
-
- /** Clears everything from the cache.
- Also invalidates the forst returned by GetFortsForChunk(). */
- void ClearCache(void);
-
- /** Returns all forts that *may* intersect the given chunk.
- The returned forts live within m_Cache.They are valid until the next call
- to this function (which may delete some of the pointers). */
- void GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts);
-
- // cFinishGen overrides:
- virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
-
- // cPiecePool overrides:
- virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
- virtual cPieces GetStartingPieces(void) override;
- virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
- virtual void PiecePlaced(const cPiece & a_Piece) override;
- virtual void Reset(void) override;
+ // cGridStructGen overrides:
+ virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
} ;
diff --git a/src/Generating/PrefabPiecePool.cpp b/src/Generating/PrefabPiecePool.cpp
new file mode 100644
index 000000000..ed9340815
--- /dev/null
+++ b/src/Generating/PrefabPiecePool.cpp
@@ -0,0 +1,121 @@
+
+// PrefabPiecePool.cpp
+
+// Implements the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces
+
+#include "Globals.h"
+#include "PrefabPiecePool.h"
+
+
+
+
+
+cPrefabPiecePool::cPrefabPiecePool(
+ const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
+ const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
+)
+{
+ AddPieceDefs(a_PieceDefs, a_NumPieceDefs);
+ if (a_StartingPieceDefs != NULL)
+ {
+ AddStartingPieceDefs(a_StartingPieceDefs, a_NumStartingPieceDefs);
+ }
+}
+
+
+
+
+
+void cPrefabPiecePool::AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs)
+{
+ ASSERT(a_PieceDefs != NULL);
+ for (size_t i = 0; i < a_NumPieceDefs; i++)
+ {
+ cPrefab * Prefab = new cPrefab(a_PieceDefs[i]);
+ m_AllPieces.push_back(Prefab);
+ AddToPerConnectorMap(Prefab);
+ }
+}
+
+
+
+
+
+void cPrefabPiecePool::AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs)
+{
+ ASSERT(a_StartingPieceDefs != NULL);
+ for (size_t i = 0; i < a_NumStartingPieceDefs; i++)
+ {
+ cPrefab * Prefab = new cPrefab(a_StartingPieceDefs[i]);
+ m_StartingPieces.push_back(Prefab);
+ }
+}
+
+
+
+
+
+void cPrefabPiecePool::AddToPerConnectorMap(cPrefab * a_Prefab)
+{
+ cPiece::cConnectors Connectors = ((const cPiece *)a_Prefab)->GetConnectors();
+ for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
+ {
+ m_PiecesByConnector[itr->m_Type].push_back(a_Prefab);
+ }
+}
+
+
+
+
+cPieces cPrefabPiecePool::GetPiecesWithConnector(int a_ConnectorType)
+{
+ return m_PiecesByConnector[a_ConnectorType];
+}
+
+
+
+
+
+cPieces cPrefabPiecePool::GetStartingPieces(void)
+{
+ if (m_StartingPieces.empty())
+ {
+ return m_AllPieces;
+ }
+ else
+ {
+ return m_StartingPieces;
+ }
+}
+
+
+
+
+
+int cPrefabPiecePool::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
+{
+ return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
+}
+
+
+
+
+
+void cPrefabPiecePool::PiecePlaced(const cPiece & a_Piece)
+{
+ // Do nothing
+ UNUSED(a_Piece);
+}
+
+
+
+
+
+void cPrefabPiecePool::Reset(void)
+{
+ // Do nothing
+}
+
+
+
+
diff --git a/src/Generating/PrefabPiecePool.h b/src/Generating/PrefabPiecePool.h
new file mode 100644
index 000000000..c6a5ad360
--- /dev/null
+++ b/src/Generating/PrefabPiecePool.h
@@ -0,0 +1,79 @@
+
+// PrefabPiecePool.h
+
+// Declares the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces
+
+
+
+
+
+#pragma once
+
+#include "PieceGenerator.h"
+#include "Prefab.h"
+
+
+
+
+
+class cPrefabPiecePool :
+ public cPiecePool
+{
+public:
+ /** Creates an empty instance. Prefabs can be added by calling AddPieceDefs() and AddStartingPieceDefs(). */
+ cPrefabPiecePool(void);
+
+ /** Creates a piece pool with prefabs from the specified definitions.
+ If both a_PieceDefs and a_StartingPieceDefs are given, only the a_StartingPieceDefs are used as starting
+ pieces for the pool, and they do not participate in the generation any further.
+ If only a_PieceDefs is given, any such piece can be chosen as a starting piece, and all the pieces are used
+ for generating.
+ More pieces can be added to the instance afterwards by calling AddPieceDefs() and AddStartingPieceDefs(). */
+ cPrefabPiecePool(
+ const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
+ const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
+ );
+
+ /** Adds pieces from the specified definitions into m_AllPieces. Also adds the pieces into
+ the m_PiecesByConnector map.
+ May be called multiple times with different PieceDefs, will add all such pieces. */
+ void AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs);
+
+ /** Adds pieces from the specified definitions into m_StartingPieces. Doesn't add them to
+ the m_PiecesByConnector map.
+ May be called multiple times with different PieceDefs, will add all such pieces. */
+ void AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs);
+
+
+protected:
+
+ /** The type used to map a connector type to the list of pieces with that connector */
+ typedef std::map<int, cPieces> cPiecesMap;
+
+ /** All the pieces that are allowed for building.
+ This is the list that's used for memory allocation and deallocation for the pieces. */
+ cPieces m_AllPieces;
+
+ /** The pieces that are used as starting pieces.
+ This list is not shared and the pieces need deallocation. */
+ cPieces m_StartingPieces;
+
+ /** The map that has all pieces by their connector types
+ The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
+ cPiecesMap m_PiecesByConnector;
+
+
+ /** Adds the prefab to the m_PiecesByConnector map for all its connectors. */
+ void AddToPerConnectorMap(cPrefab * a_Prefab);
+
+ // cPiecePool overrides:
+ virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
+ virtual cPieces GetStartingPieces(void) override;
+ virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
+ virtual void PiecePlaced(const cPiece & a_Piece) override;
+ virtual void Reset(void) override;
+} ;
+
+
+
+