simplify puzzle data and auto run codegen

This commit is contained in:
Asuro
2025-03-14 01:33:38 +01:00
parent 97146664f2
commit de88190c47
9 changed files with 82 additions and 143 deletions

View File

@@ -60,24 +60,6 @@ namespace Generated
return data.Cards[H.Idx];
}
bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search)
{
for (int32_t i = 0; i < Puzzle::Config::MaxElementsPerTile; ++i)
{
if (node.PlacedTypes[i] == search) return true;
}
return false;
}
bool IsEmpty(const PuzzleNode& node)
{
for (int32_t i = 0; i < Puzzle::Config::MaxElementsPerTile; ++i)
{
if (node.PlacedTypes[i] != PuzzleElementType::None) return false;
}
return true;
}
bool IsValid(StaticPuzzleCardHandle h)
{
return h.Idx != UINT16_MAX;
@@ -89,18 +71,43 @@ namespace Generated
return stack.MaxAvailableCount - stack.UsedCount;
}
const PuzzleNode& GetNodeAt(const PuzzleData& puz, PuzPos pos)
PuzzleElementType::Enum GetNodeAt(const PuzzleData& puz, PuzPos pos)
{
assert(pos.X < Puzzle::Config::MaxPuzzleSizeCards && pos.Y < Puzzle::Config::MaxPuzzleSizeCards && pos.X >= 0 &&
pos.Y >= 0);
return puz.PlacedNodes[pos.Y * Puzzle::Config::MaxPuzzleSizeCards + pos.X];
// TODO: this is horrible
for (int32_t i = 0; i < puz.PlacedCardCount; ++i)
{
auto& card = puz.PlacedCards[i];
int8_t offsetX = pos.X - card.Position.X;
int8_t offsetY = pos.Y - card.Position.Y;
if (offsetX >= 0 && offsetX < Puzzle::Config::CardSize && offsetY >= 0 &&
offsetY < Puzzle::Config::CardSize)
{
PuzzleElementType::Enum cardVal =
GetCardNodeAt(GetCard(GetStaticPuzzleData(), card.RefCard), offsetX, offsetY);
if (cardVal != PuzzleElementType::None) return cardVal;
}
}
return puz.BackgroundTiles[pos.Y * Puzzle::Config::MaxPuzzleSizeCards + pos.X];
}
PuzzleElementType::Enum GetElementAt(const PuzzleData& puz, ElemPos pos)
PuzzleElementType::Enum GetCardNodeAt(const StaticPuzzleCard& card, int8_t x, int8_t y)
{
assert(pos.ElemIdx < Puzzle::Config::MaxElementsPerTile);
const PuzzleNode& node = GetNodeAt(puz, pos.Position);
return node.PlacedTypes[pos.ElemIdx];
assert(x >= 0 && x < Puzzle::Config::CardSize);
assert(y >= 0 && y < Puzzle::Config::CardSize);
// TODO: account for card rotation
return card.Elements[y * Puzzle::Config::CardSize + x];
}
PuzzleElementType::Enum& EditCardNodeAt(StaticPuzzleCard& card, int8_t x, int8_t y)
{
assert(x >= 0 && x < Puzzle::Config::CardSize);
assert(y >= 0 && y < Puzzle::Config::CardSize);
// TODO: account for card rotation
return card.Elements[y * Puzzle::Config::CardSize + x];
}
bool PuzzleSolver::IsPuzzleSolved(const PuzzleData& puzzle)
@@ -117,16 +124,15 @@ namespace Generated
return IsSolved;
}
bool PuzzleSolver::IsExitSatisfied(const PuzzleData& puzzle, ElemPos pos)
bool PuzzleSolver::IsExitSatisfied(const PuzzleData& puzzle, PuzPos pos)
{
const PuzzleNode& goalNode = GetNodeAt(puzzle, pos.Position);
PuzzleElementType::Enum goalType = GetElementAt(puzzle, pos);
PuzzleElementType::Enum goalType = GetNodeAt(puzzle, pos);
uint32_t currentPositionQueueIdx = 0;
uint32_t positionQueueCount = 0;
PuzPos positionQueue[Puzzle::Config::MaxTilesInPuzzle];
positionQueue[0] = pos.Position;
positionQueue[0] = pos;
positionQueueCount++;
while (positionQueueCount > 0)
{
@@ -137,13 +143,9 @@ namespace Generated
PuzPos nextPos = currentPos + dir;
if (IsValidGoalConnection(puzzle, nextPos, currentPos, goalType))
{
const PuzzleNode& node = GetNodeAt(puzzle, nextPos);
for (PuzzleElementType::Enum e : node.PlacedTypes)
if (IsValidSource(GetNodeAt(puzzle, nextPos), goalType))
{
if (IsValidSource(e, goalType))
{
return true;
}
return true;
}
positionQueue[positionQueueCount] = nextPos;
positionQueueCount++;
@@ -159,18 +161,18 @@ namespace Generated
PuzPos flowTo,
PuzzleElementType::Enum goalType)
{
const PuzzleNode& from = GetNodeAt(puzzle, flowFrom);
const PuzzleNode& to = GetNodeAt(puzzle, flowTo);
auto from = GetNodeAt(puzzle, flowFrom);
auto to = GetNodeAt(puzzle, flowTo);
if (goalType == PuzzleElementType::WaterGoal)
{
return HasElement(from, PuzzleElementType::WaterIn) || HasElement(from, PuzzleElementType::WaterChannel) ||
HasElement(from, PuzzleElementType::WaterGoal);
return from == PuzzleElementType::WaterIn || from == PuzzleElementType::WaterChannel ||
from == PuzzleElementType::WaterGoal;
}
else if (goalType == PuzzleElementType::ElectricGoal)
{
return HasElement(from, PuzzleElementType::ElectricIn) ||
HasElement(from, PuzzleElementType::ElectricGoal) || IsEmpty(from);
return from == PuzzleElementType::ElectricIn || from == PuzzleElementType::ElectricGoal ||
from == PuzzleElementType::None;
}
assert(false);
return false;
@@ -192,14 +194,9 @@ namespace Generated
bx::snprintf(buf, bufSize, "%s/%u.pzl", Puzzle::PuzzleFileDir, puzID);
}
const char* GetShortNodeName(const PuzzleNode& node)
const char* GetShortNodeName(const PuzzleElementType::Enum node)
{
PuzzleElementType::Enum elemMax = PuzzleElementType::None;
for (int32_t i = 0; i < BX_COUNTOF(node.PlacedTypes); ++i)
{
if (node.PlacedTypes[i] > elemMax) elemMax = node.PlacedTypes[i];
}
return PuzzleElementType::ShortName[elemMax];
return PuzzleElementType::ShortName[node];
}
bool RenderDebugUI(PuzzleData& obj)
@@ -257,7 +254,7 @@ namespace Generated
for (int32_t x = 0; x < obj.WidthTiles; ++x)
{
ImGui::PushID(x);
PuzzleNode& node = obj.PlacedNodes[Puzzle::Config::MaxPuzzleSizeTiles * y + x];
auto node = GetNodeAt(obj, {int8_t(x), int8_t(y)});
ImVec2 pos = ImVec2{puzCursorStart.x + x * UIPuzBoxSize + 5, puzCursorStart.y + y * UIPuzBoxSize};
ImGui::SetCursorScreenPos(pos);
ImGui::Text("%s", GetShortNodeName(node));