From c2386d8d65389117031f07e2bbeeeb9f02dfb23c Mon Sep 17 00:00:00 2001 From: milan Date: Mon, 7 Nov 2022 19:05:00 +0100 Subject: [PATCH] requirements for exit door --- .../Engine/Scripts/Engine.cs | 53 ++----------------- .../Scripts/Modules/ModuleDescription.cs | 8 +-- .../Scripts/Requirements/FaceSpaceCenter.cs | 7 +-- .../Engine/Scripts/Requirements/NoOverlap.cs | 2 +- .../Requirements/OrientationRequirement.cs | 28 +++++++++- .../Requirements/PlaceAlongSpaceEdges.cs | 2 +- .../Scripts/Requirements/PlaceAnywhere.cs | 2 +- .../Requirements/PlacementRequirement.cs | 28 +++++++++- .../Scripts/Requirements/Requirement.cs | 24 +++++++-- .../Engine/Scripts/Space.cs | 12 +++++ 10 files changed, 95 insertions(+), 71 deletions(-) diff --git a/Assets/Escape Room Engine/Engine/Scripts/Engine.cs b/Assets/Escape Room Engine/Engine/Scripts/Engine.cs index 03b0ac6..71a7fd3 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Engine.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Engine.cs @@ -73,64 +73,19 @@ namespace Escape_Room_Engine.Engine.Scripts // add exit var exitDoor = new DoorModule(space, exitDoorTypes.RandomElement()); - exitDoor.Place(new Vector2Int( - Random.Range(0, rrDimensions.width), - Random.Range(0, rrDimensions.length) - )); - exitDoor.orientation = Module.EveryOrientation.RandomElement(); + if (!space.AddModuleWithRequirements(exitDoor)) + throw new Exception("Could not satisfy requirements for exit door."); var exit = new Passage(exitDoor); - space.AddModule(exitDoor); - + // add puzzles for (var i = 0; i < Utilities.Utilities.RandomInclusive(minPuzzleCount, maxPuzzleCount); i++) { - GeneratePuzzle(space); + space.AddModuleWithRequirements(new PuzzleModule(space, puzzleTypes.RandomElement())); } room.AddSpace(space, exit); } - private void GeneratePuzzle(Space space) - { - var puzzle = new PuzzleModule(space, puzzleTypes.RandomElement()); - - // place puzzle - var placementCandidates = space.rrDimensions.EveryPosition; - puzzle.description.RequirementsOfType().ForEach(requirement => - placementCandidates.IntersectWith(requirement.PlacementCandidates(puzzle, space))); - - Logger.Log($"placement candidates: {string.Join(", ", placementCandidates.ToList().ConvertAll(c => c.ToString()))}", LogType.RequirementResolution); - - if (placementCandidates.Count > 0) - { - puzzle.Place(placementCandidates.RandomElement()); - } - else - { - Logger.Log("Could not find suitable placement for puzzle", LogType.PuzzleGeneration); - return; - } - - // orient puzzle - var orientationCandidates = Module.EveryOrientation; - puzzle.description.RequirementsOfType().ForEach(requirement => - orientationCandidates.IntersectWith(requirement.OrientationCandidates(puzzle, space))); - - Logger.Log($"orientation candidates: {string.Join(",", orientationCandidates.ToList().ConvertAll(c => c.ToString()))}", LogType.RequirementResolution); - - if (orientationCandidates.Count > 0) - { - puzzle.orientation = orientationCandidates.RandomElement(); - } - else - { - Logger.Log("Could not find suitable orientation for puzzle", LogType.PuzzleGeneration); - return; - } - - space.AddModule(puzzle); - } - /// /// Generate space dimensions that fit the required size constraints and cover the position of the entrance. /// diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleDescription.cs b/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleDescription.cs index 03066d3..54c1eaf 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleDescription.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleDescription.cs @@ -9,11 +9,7 @@ namespace Escape_Room_Engine.Engine.Scripts.Modules { public List types = new(); public GameObject modulePrefab; - public List requirements = new(); - - public List RequirementsOfType() where T : Requirement - { - return requirements.FindAll(requirement => requirement is T).ConvertAll(requirement => (T)requirement); - } + public List placementRequirements = new(); + public List orientationRequirements = new(); } } \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Requirements/FaceSpaceCenter.cs b/Assets/Escape Room Engine/Engine/Scripts/Requirements/FaceSpaceCenter.cs index 1eff5fd..1e2e121 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Requirements/FaceSpaceCenter.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Requirements/FaceSpaceCenter.cs @@ -1,24 +1,19 @@ using System.Collections.Generic; using Escape_Room_Engine.Engine.Scripts.Modules; -using Unity.XR.CoreUtils; using UnityEngine; -using Logger = Escape_Room_Engine.Engine.Scripts.Utilities.Logger; -using LogType = Escape_Room_Engine.Engine.Scripts.Utilities.LogType; namespace Escape_Room_Engine.Engine.Scripts.Requirements { [CreateAssetMenu(menuName = "Requirements/Face Space Center")] public class FaceSpaceCenter : OrientationRequirement { - public override IEnumerable OrientationCandidates(Module module, Space space) + protected override IEnumerable GenerateCandidates(Module module, Space space) { var orientation = new HashSet(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); - - Debug.Log($"{xRel}, {zRel}, {1 - xRel}"); if (zRel > xRel) { diff --git a/Assets/Escape Room Engine/Engine/Scripts/Requirements/NoOverlap.cs b/Assets/Escape Room Engine/Engine/Scripts/Requirements/NoOverlap.cs index 9921e18..a247354 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Requirements/NoOverlap.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Requirements/NoOverlap.cs @@ -7,7 +7,7 @@ namespace Escape_Room_Engine.Engine.Scripts.Requirements [CreateAssetMenu(menuName = "Requirements/No Overlap")] public class NoOverlap : PlacementRequirement { - public override IEnumerable PlacementCandidates(Module module, Space space) + protected override IEnumerable GenerateCandidates(Module module, Space space) { var edgePositions = space.rrDimensions.EveryPosition; diff --git a/Assets/Escape Room Engine/Engine/Scripts/Requirements/OrientationRequirement.cs b/Assets/Escape Room Engine/Engine/Scripts/Requirements/OrientationRequirement.cs index e574824..63190c9 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Requirements/OrientationRequirement.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Requirements/OrientationRequirement.cs @@ -1,10 +1,34 @@ using System.Collections.Generic; +using System.Linq; using Escape_Room_Engine.Engine.Scripts.Modules; +using Escape_Room_Engine.Engine.Scripts.Utilities; namespace Escape_Room_Engine.Engine.Scripts.Requirements { - public abstract class OrientationRequirement : Requirement + public abstract class OrientationRequirement : Requirement { - public abstract IEnumerable OrientationCandidates(Module module, Space space); + protected abstract override IEnumerable GenerateCandidates(Module module, Space space); + + public static bool TryOrienting(Module module, Space space) + { + 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.PuzzleGeneration); + return false; + } + } } } \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAlongSpaceEdges.cs b/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAlongSpaceEdges.cs index d9c11ee..ebb39ef 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAlongSpaceEdges.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAlongSpaceEdges.cs @@ -7,7 +7,7 @@ namespace Escape_Room_Engine.Engine.Scripts.Requirements [CreateAssetMenu(menuName = "Requirements/Place Along Space Edges")] public class PlaceAlongSpaceEdges : PlacementRequirement { - public override IEnumerable PlacementCandidates(Module module, Space space) + protected override IEnumerable GenerateCandidates(Module module, Space space) { var edgePositions = new HashSet(); diff --git a/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAnywhere.cs b/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAnywhere.cs index db58299..fd08ac1 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAnywhere.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlaceAnywhere.cs @@ -7,7 +7,7 @@ namespace Escape_Room_Engine.Engine.Scripts.Requirements [CreateAssetMenu(menuName = "Requirements/Place Anywhere")] public class PlaceAnywhere : PlacementRequirement { - public override IEnumerable PlacementCandidates(Module module, Space space) + protected override IEnumerable GenerateCandidates(Module module, Space space) { return space.rrDimensions.EveryPosition; } diff --git a/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlacementRequirement.cs b/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlacementRequirement.cs index 4f34888..c9bda5c 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlacementRequirement.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Requirements/PlacementRequirement.cs @@ -1,11 +1,35 @@ using System.Collections.Generic; +using System.Linq; using Escape_Room_Engine.Engine.Scripts.Modules; +using Escape_Room_Engine.Engine.Scripts.Utilities; using UnityEngine; namespace Escape_Room_Engine.Engine.Scripts.Requirements { - public abstract class PlacementRequirement : Requirement + public abstract class PlacementRequirement : Requirement { - public abstract IEnumerable PlacementCandidates(Module module, Space space); + protected abstract override IEnumerable GenerateCandidates(Module module, Space space); + + public static bool TryPlacing(Module module, Space space) + { + var placementCandidates = Candidates( + space.rrDimensions.EveryPosition, + module.description.placementRequirements, + module, space); + + Utilities.Logger.Log($"placement candidates: {string.Join(", ", placementCandidates.ToList().ConvertAll(c => c.ToString()))}", Utilities.LogType.RequirementResolution); + + if (placementCandidates.Count > 0) + { + module.Place(placementCandidates.RandomElement()); + return true; + } + // ReSharper disable once RedundantIfElseBlock + else + { + Utilities.Logger.Log("Could not find suitable placement for module", Utilities.LogType.PuzzleGeneration); + return false; + } + } } } \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Requirements/Requirement.cs b/Assets/Escape Room Engine/Engine/Scripts/Requirements/Requirement.cs index ed9af31..c865e2d 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Requirements/Requirement.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Requirements/Requirement.cs @@ -1,9 +1,27 @@ -using UnityEngine; +using System.Collections.Generic; +using Escape_Room_Engine.Engine.Scripts.Modules; +using UnityEngine; namespace Escape_Room_Engine.Engine.Scripts.Requirements { - public abstract class Requirement : ScriptableObject + public abstract class Requirement : ScriptableObject { - + protected abstract IEnumerable GenerateCandidates(Module module, Space space); + + public void Restrict(HashSet candidates, Module module, Space space) => + candidates.IntersectWith(GenerateCandidates(module, space)); + + public static HashSet Candidates( + HashSet initialCandidates, + IEnumerable> requirements, + Module module, Space space) + { + foreach (var requirement in requirements) + { + requirement.Restrict(initialCandidates, module, space); + } + + return initialCandidates; + } } } \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Space.cs b/Assets/Escape Room Engine/Engine/Scripts/Space.cs index d17d78c..b68388a 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Space.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Space.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Escape_Room_Engine.Engine.Scripts.Modules; +using Escape_Room_Engine.Engine.Scripts.Requirements; using UnityEngine; namespace Escape_Room_Engine.Engine.Scripts @@ -29,6 +30,17 @@ namespace Escape_Room_Engine.Engine.Scripts Modules.Add(module); } + internal bool AddModuleWithRequirements(Module module) + { + var result = + PlacementRequirement.TryPlacing(module, this) && + OrientationRequirement.TryOrienting(module, this); + + AddModule(module); + + return result; + } + internal void InstantiateSpace(Transform parent, string name) { _spaceObject = new GameObject($"Space {name}", typeof(MeshFilter), typeof(MeshRenderer));