simplify puzzle data and auto run codegen
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -31,17 +31,16 @@ namespace Generated
|
||||
void LoadStaticPuzzleData();
|
||||
void SaveStaticPuzzleData();
|
||||
const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H);
|
||||
bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search);
|
||||
bool IsEmpty(const PuzzleNode& node);
|
||||
bool IsValid(StaticPuzzleCardHandle h);
|
||||
uint8_t GetRemainingCount(const PuzzleCardStack& stack);
|
||||
const PuzzleNode& GetNodeAt(const PuzzleData& puz, PuzPos pos);
|
||||
PuzzleElementType::Enum GetElementAt(const PuzzleData& puz, ElemPos pos);
|
||||
PuzzleElementType::Enum GetNodeAt(const PuzzleData& puz, PuzPos pos);
|
||||
PuzzleElementType::Enum GetCardNodeAt(const StaticPuzzleCard& card, int8_t x, int8_t y);
|
||||
PuzzleElementType::Enum& EditCardNodeAt(StaticPuzzleCard& card, int8_t x, int8_t y);
|
||||
|
||||
struct PuzzleSolver
|
||||
{
|
||||
bool IsPuzzleSolved(const Generated::PuzzleData& puzzle);
|
||||
bool IsExitSatisfied(const Generated::PuzzleData& puzzle, ElemPos pos);
|
||||
bool IsExitSatisfied(const Generated::PuzzleData& puzzle, PuzPos pos);
|
||||
|
||||
// This assumes flowFrom is already verified to be connected.
|
||||
bool IsValidGoalConnection(const Generated::PuzzleData& puzzle,
|
||||
|
||||
BIN
src/game/data/puzzles/0.pzl
LFS
BIN
src/game/data/puzzles/0.pzl
LFS
Binary file not shown.
Binary file not shown.
@@ -44,12 +44,6 @@ type PuzPos
|
||||
i8 Y
|
||||
}
|
||||
|
||||
type ElemPos
|
||||
{
|
||||
PuzPos Position
|
||||
u8 ElemIdx
|
||||
}
|
||||
|
||||
enum PuzzleElementType(u8)
|
||||
{
|
||||
None GameName("Empty") ShortName(" ")
|
||||
@@ -62,15 +56,10 @@ enum PuzzleElementType(u8)
|
||||
Bridge GameName("Bridge") ShortName("#")
|
||||
}
|
||||
|
||||
type PuzzleNode
|
||||
{
|
||||
PuzzleElementType PlacedTypes Arr(4)
|
||||
}
|
||||
|
||||
type StaticPuzzleCard
|
||||
{
|
||||
PuzzleNode Nodes Arr(4)
|
||||
u16 ModelHandle
|
||||
PuzzleElementType Elements Arr(4)
|
||||
u16 ModelHandle
|
||||
}
|
||||
|
||||
type StaticPuzzleCardHandle
|
||||
@@ -108,7 +97,7 @@ type PuzzleData
|
||||
PuzzleCardStack AvailableCards Arr(16)
|
||||
u32 PlacedCardCount
|
||||
PlacedPuzzleCard PlacedCards Arr(256)
|
||||
PuzzleNode PlacedNodes Arr(1024)
|
||||
PuzzleElementType BackgroundTiles Arr(1024)
|
||||
u32 GoalPositionCount
|
||||
ElemPos GoalPositions Arr(16)
|
||||
PuzPos GoalPositions Arr(16)
|
||||
}
|
||||
|
||||
@@ -603,22 +603,22 @@ namespace Game
|
||||
}
|
||||
|
||||
Tools::ModelDropdown(card.ModelHandle);
|
||||
for (int32_t y = 0; y < Puzzle::Config::CardSize; ++y)
|
||||
for (int8_t y = 0; y < Puzzle::Config::CardSize; ++y)
|
||||
{
|
||||
ImGui::PushID(y);
|
||||
for (int32_t x = 0; x < Puzzle::Config::CardSize; ++x)
|
||||
for (int8_t x = 0; x < Puzzle::Config::CardSize; ++x)
|
||||
{
|
||||
if (x > 0) ImGui::SameLine();
|
||||
ImGui::PushID(x);
|
||||
auto& node = card.Nodes[y * Puzzle::Config::CardSize + x];
|
||||
if (ImGui::Button(Generated::PuzzleElementType::ShortName[node.PlacedTypes[0]], {26, 24}))
|
||||
auto& node = Generated::EditCardNodeAt(card, x, y);
|
||||
if (ImGui::Button(Generated::PuzzleElementType::ShortName[node], {26, 24}))
|
||||
{
|
||||
int32_t newVal = int32_t(node.PlacedTypes[0]) + 1;
|
||||
int32_t newVal = int32_t(node) + 1;
|
||||
if (newVal >= Generated::PuzzleElementType::EntryCount)
|
||||
{
|
||||
newVal = 0;
|
||||
}
|
||||
node.PlacedTypes[0] = Generated::PuzzleElementType::Enum(newVal);
|
||||
node = Generated::PuzzleElementType::Enum(newVal);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user