rework dimensions and orientation into Placement, optimise requirements to work on previous candidates, use vec3 for positions

This commit is contained in:
2022-11-24 11:34:11 +01:00
parent f13ba4cd95
commit 3e51410ade
36 changed files with 268 additions and 275 deletions

View File

@@ -5,26 +5,29 @@ using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
[CreateAssetMenu(menuName = "Requirements/Face Space Center")]
public class FaceSpaceCenter : OrientationRequirement
public class FaceSpaceCenter : PlacementRequirement
{
protected override IEnumerable<Orientation> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
var orientation = new HashSet<Orientation>(1);
float width = space.rrDimensions.width;
float length = space.rrDimensions.length;
var xRel = module.SrPosition.x / (width - 1);
var zRel = module.SrPosition.y / (length - 1);
if (zRel > xRel)
{
orientation.Add(zRel > 1 - xRel ? Orientation.South : Orientation.East);
}
else
{
orientation.Add(zRel > 1 - xRel ? Orientation.West : Orientation.North);
}
float width = space.rrPlacement.size.x - 1;
float length = space.rrPlacement.size.y - 1;
return orientation;
candidates.RemoveAll(candidate =>
{
var xRel = candidate.position.x / width;
var zRel = candidate.position.z / length;
return candidate.orientation !=
(zRel > xRel
? zRel > 1 - xRel
? Orientation.South
: Orientation.East
: zRel > 1 - xRel
? Orientation.West
: Orientation.North);
});
return candidates;
}
}
}

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Modules;
using NaughtyAttributes;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
@@ -8,21 +7,11 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[CreateAssetMenu(menuName = "Requirements/No Overlap")]
public class NoOverlap : PlacementRequirement
{
[InfoBox("A module relative position will be oriented with the module (e.g. (0, 1) is always in front of the module).")]
[Label("Reserved Positions (Module Relative)")]
public List<Vector2Int> mrReservedPositions;
protected override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
var candidates = space.rrDimensions.EveryPosition;
space.AllModules.ForEach(m =>
space.AllModules.ForEach(other =>
{
candidates.Remove(m.SrPosition);
m.description.placementRequirements
.FindAll(r => r is NoOverlap)
.ForEach(r => ((NoOverlap)r).mrReservedPositions
.ForEach(p => candidates.Remove(m.ToSpaceRelative(p))));
candidates.RemoveAll(candidate => candidate.position.Equals(other.SrPosition));
});
return candidates;

View File

@@ -1,40 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Utilities;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class OrientationRequirement : Requirement<Orientation>
{
protected abstract override IEnumerable<Orientation> GenerateCandidates(Module module, Space space);
public static bool TryOrienting(Module module, Space space)
{
if (module.description.orientationRequirements.Count == 0)
{
// don't evaluate requirements if there are none
return true;
}
var orientationCandidates = Candidates(
Module.EveryOrientation,
module.description.orientationRequirements,
module, space);
Logger.Log($"orientation candidates: {string.Join(",", orientationCandidates.ToList().ConvertAll(c => c.ToString()))}", LogType.RequirementResolution);
if (orientationCandidates.Count > 0)
{
module.orientation = orientationCandidates.RandomElement();
return true;
}
// ReSharper disable once RedundantIfElseBlock
else
{
Logger.Log("Could not find suitable orientation for module", LogType.RequirementResolution);
return false;
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 0704ea5393394baf921f68d2dcbdfaec
timeCreated: 1667878220

View File

@@ -7,22 +7,18 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[CreateAssetMenu(menuName = "Requirements/Place Along Space Edges")]
public class PlaceAlongSpaceEdges : PlacementRequirement
{
protected override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
var edgePositions = new HashSet<Vector2Int>();
var right = space.rrPlacement.size.x - 1;
var top = space.rrPlacement.size.y - 1;
for (var x = 0; x < space.rrDimensions.width; x++)
candidates.RemoveAll(candidate =>
{
edgePositions.Add(new Vector2Int(x, 0));
edgePositions.Add(new Vector2Int(x, space.rrDimensions.length - 1));
}
for (var z = 0; z < space.rrDimensions.length; z++)
{
edgePositions.Add(new Vector2Int(0, z));
edgePositions.Add(new Vector2Int(space.rrDimensions.width - 1, z));
}
var position = candidate.position;
return position.x > 0 && position.x < right && position.z > 0 && position.z < top;
});
return edgePositions;
return candidates;
}
}
}

View File

@@ -7,9 +7,9 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[CreateAssetMenu(menuName = "Requirements/Place Anywhere")]
public class PlaceAnywhere : PlacementRequirement
{
protected override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
return space.rrDimensions.EveryPosition;
return candidates;
}
}
}

View File

@@ -2,15 +2,12 @@
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using UnityEngine;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class PlacementRequirement : Requirement<Vector2Int>
public abstract class PlacementRequirement : Requirement<Placement>
{
protected abstract override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space);
protected abstract override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space);
public static bool TryPlacing(Module module, Space space)
{
@@ -21,11 +18,11 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
}
var placementCandidates = Candidates(
space.rrDimensions.EveryPosition,
space.rrPlacement.EveryPlacement,
module.description.placementRequirements,
module, space);
Logger.Log($"placement candidates: {string.Join(", ", placementCandidates.ToList().ConvertAll(c => c.ToString()))}", LogType.RequirementResolution);
Logger.Log($"placement candidates: {string.Join(", ", placementCandidates.ToList().ConvertAll(c => c.PositionAndOrientation()))}", LogType.RequirementResolution);
if (placementCandidates.Count > 0)
{

View File

@@ -7,9 +7,9 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class PreconditionRequirement : Requirement<bool>
{
protected static readonly HashSet<bool> TrueSet = new(new[] { true }), FalseSet = new(new[] { false });
private static readonly List<bool> TrueSet = new(new[] { true });
protected abstract override IEnumerable<bool> GenerateCandidates(Module module, Space space);
protected abstract override List<bool> FilterCandidates(List<bool> candidates, Module module, Space space);
public static bool CheckPreconditions(Module module, Space space)
{

View File

@@ -12,12 +12,12 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[Required]
public ModuleDescription relatedModule;
protected override IEnumerable<bool> GenerateCandidates(Module module, Space space)
protected override List<bool> FilterCandidates(List<bool> candidates, Module module, Space space)
{
var newModule = Module.CreateModuleByType(space, relatedModule);
module.relatedModules.Add(newModule);
return new []{ space.StageModuleWithRequirements(newModule) };
return new List<bool> { space.StageModuleWithRequirements(newModule) };
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Modules;
using UnityEngine;
@@ -6,22 +7,15 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class Requirement<T> : ScriptableObject
{
protected abstract IEnumerable<T> GenerateCandidates(Module module, Space space);
protected abstract List<T> FilterCandidates(List<T> candidates, Module module, Space space);
public void Restrict(HashSet<T> candidates, Module module, Space space) =>
candidates.IntersectWith(GenerateCandidates(module, space));
public static HashSet<T> Candidates(
HashSet<T> initialCandidates,
protected static List<T> Candidates(
List<T> candidates,
IEnumerable<Requirement<T>> requirements,
Module module, Space space)
{
foreach (var requirement in requirements)
{
requirement.Restrict(initialCandidates, module, space);
}
return initialCandidates;
return requirements.Aggregate(candidates,
(current, requirement) => requirement.FilterCandidates(current, module, space));
}
}
}