puzzle setup

This commit is contained in:
Asuro
2025-02-22 03:04:36 +01:00
parent 833d78c142
commit d7ed08eb08
2 changed files with 232 additions and 0 deletions

112
src/game/Puzzle.cpp Normal file
View File

@@ -0,0 +1,112 @@
#include "Puzzle.h"
#include <cassert>
namespace
{
static constexpr Puzzle::PuzPos Dirs[4]{
{-1, 0},
{0, -1},
{0, 1},
{1, 0},
};
}
namespace Puzzle
{
bool PuzzleNode::HasElement(PuzzleElementType search) const
{
for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i)
{
if (PlacedTypes[i] == search) return true;
}
return false;
}
bool PuzzleNode::IsEmpty() const
{
for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i)
{
if (PlacedTypes[i] != PuzzleElementType::None) return false;
}
return true;
}
uint8_t PuzzleCardStack::GetRemainingCount()
{
assert(MaxAvailableCount >= UsedCount);
return MaxAvailableCount - UsedCount;
}
bool PuzzleSolver::IsPuzzleSolved(const PuzzleData& puzzle)
{
bool IsSolved = true;
for (uint32_t i = 0; i < puzzle.GoalPositionCount; ++i)
{
}
return IsSolved;
}
bool PuzzleSolver::IsExitSatisfied(const PuzzleData& puzzle, ElemPos pos)
{
const PuzzleNode& goalNode = puzzle.GetNodeAt(pos.Position);
PuzzleElementType goalType = puzzle.GetElementAt(pos);
uint32_t currentPositionQueueIdx = 0;
uint32_t positionQueueCount = 0;
PuzPos positionQueue[Config::MaxTilesInPuzzle];
positionQueue[0] = pos.Position;
positionQueueCount++;
while (positionQueueCount > 0)
{
assert(currentPositionQueueIdx < Config::MaxTilesInPuzzle);
PuzPos currentPos = positionQueue[currentPositionQueueIdx];
for (PuzPos dir : Dirs)
{
PuzPos nextPos = currentPos + dir;
if (IsValidGoalConnection(puzzle, nextPos, currentPos, goalType))
{
const PuzzleNode& node = puzzle.GetNodeAt(nextPos);
for (PuzzleElementType e : node.PlacedTypes)
{
if (IsValidSource(e, goalType))
{
return true;
}
}
positionQueue[positionQueueCount] = nextPos;
positionQueueCount++;
}
}
currentPositionQueueIdx++;
}
return false;
}
bool PuzzleSolver::IsValidGoalConnection(const PuzzleData& puzzle,
PuzPos flowFrom,
PuzPos flowTo,
PuzzleElementType goalType)
{
const PuzzleNode& from = puzzle.GetNodeAt(flowFrom);
const PuzzleNode& to = puzzle.GetNodeAt(flowTo);
if (goalType == PuzzleElementType::WaterGoal)
{
return from.HasElement(PuzzleElementType::WaterIn) || from.HasElement(PuzzleElementType::WaterChannel) ||
from.HasElement(PuzzleElementType::WaterGoal);
}
else if (goalType == PuzzleElementType::ElectricGoal)
{
return from.HasElement(PuzzleElementType::ElectricIn) || from.HasElement(PuzzleElementType::ElectricGoal) ||
from.IsEmpty();
}
assert(false);
return false;
}
bool PuzzleSolver::IsValidSource(PuzzleElementType sourceType, PuzzleElementType goalType)
{
return (sourceType == PuzzleElementType::WaterIn && goalType == PuzzleElementType::WaterGoal) ||
(sourceType == PuzzleElementType::ElectricIn && goalType == PuzzleElementType::ElectricGoal);
}
} // namespace Puzzle