using System.Collections.Generic; using System.Linq; namespace ManifoldGardenArchipelago { public struct RequirementReferences { public RequirementReferences() { } public readonly HashSet scenes = []; public readonly HashSet buttons = []; public readonly HashSet sockets = []; public readonly HashSet pads = []; public readonly HashSet waterwheels = []; public readonly HashSet spheres = []; public readonly HashSet items = []; public void Merge(RequirementReferences other) { foreach (var item in other.scenes) { scenes.Add(item); } foreach (var item in other.buttons) { buttons.Add(item); } foreach (var item in other.sockets) { sockets.Add(item); } foreach (var item in other.pads) { pads.Add(item); } foreach (var item in other.waterwheels) { waterwheels.Add(item); } foreach (var item in other.spheres) { spheres.Add(item); } foreach (var item in other.items) { items.Add(item); } } } public abstract class Requirement { public enum Decision { Maybe, No, Yes, } public RequirementReferences references = new(); public abstract Decision Check(); } public class AndRequirement : Requirement { private readonly List _requirements; public AndRequirement(List requirements) { _requirements = requirements; foreach (var subreq in _requirements) { references.Merge(subreq.references); } } public override Decision Check() { foreach (var requirement in _requirements) { Decision decision = requirement.Check(); if (decision != Decision.Yes) { return decision; } } return Decision.Yes; } public override string ToString() { return "And(" + string.Join(", ", _requirements.Select((req) => req.ToString())) + ")"; } } public class OrRequirement : Requirement { private readonly List _requirements; public OrRequirement(List requirements) { _requirements = requirements; foreach (var subreq in _requirements) { references.Merge(subreq.references); } } public override Decision Check() { bool sawMaybe = false; foreach (var requirement in _requirements) { Decision decision = requirement.Check(); if (decision == Decision.Yes) { return decision; } else if (decision == Decision.Maybe) { sawMaybe = true; } } return sawMaybe ? Decision.Maybe : Decision.No; } public override string ToString() { return "Or(" + string.Join(", ", _requirements.Select((req) => req.ToString())) + ")"; } } public class ItemRequirement : Requirement { private readonly string _itemName; public ItemRequirement(string itemName) { _itemName = itemName; references.items.Add(itemName); } public override Decision Check() { return Plugin.archipelagoManager.HasItem(_itemName) ? Decision.Yes : Decision.No; } public override string ToString() { return $"Item({_itemName})"; } } public class EntryRequirement : Requirement { private readonly string _sceneName; public EntryRequirement(string sceneName) { _sceneName = sceneName; references.scenes.Add(sceneName); } public override Decision Check() { return Plugin.slotSave.VisitedScenes.Contains(_sceneName) ? Decision.Yes : Decision.No; } public override string ToString() { return $"Entry({_sceneName})"; } } public class ButtonRequirement : Requirement { private readonly SceneItemReference _button; public ButtonRequirement(SceneItemReference button) { _button = button; references.scenes.Add(button.scene); references.buttons.Add(button); } public override Decision Check() { if (Plugin.slotSave.ActivatedButtons.TryGetValue(_button, out bool value)) { return value ? Decision.Yes : Decision.No; } else { return Decision.Maybe; } } public override string ToString() { return $"Button{_button}"; } } public class SocketRequirement : Requirement { private readonly SceneItemReference _socket; public SocketRequirement(SceneItemReference socket) { _socket = socket; references.scenes.Add(socket.scene); references.sockets.Add(socket); } public override Decision Check() { if (Plugin.slotSave.ActivatedSockets.TryGetValue(_socket, out bool value)) { return value ? Decision.Yes : Decision.No; } else { return Decision.Maybe; } } public override string ToString() { return $"Socket{_socket}"; } } public class PadRequirement : Requirement { private readonly SceneItemReference _pad; public PadRequirement(SceneItemReference pad) { _pad = pad; references.scenes.Add(pad.scene); references.pads.Add(pad); } public override Decision Check() { if (Plugin.slotSave.ActivatedPads.TryGetValue(_pad, out bool value)) { return value ? Decision.Yes : Decision.No; } else { return Decision.Maybe; } } public override string ToString() { return $"Pad{_pad}"; } } public class WaterwheelRequirement : Requirement { private readonly SceneItemReference _waterwheel; public WaterwheelRequirement(SceneItemReference waterwheel) { _waterwheel = waterwheel; references.scenes.Add(waterwheel.scene); references.waterwheels.Add(waterwheel); } public override Decision Check() { if (Plugin.slotSave.ActivatedWaterwheels.TryGetValue(_waterwheel, out bool value)) { return value ? Decision.Yes : Decision.No; } else { return Decision.Maybe; } } public override string ToString() { return $"Waterwheel{_waterwheel}"; } } public class SphereRequirement : Requirement { private readonly SceneItemReference _sphere; public SphereRequirement(SceneItemReference sphere) { _sphere = sphere; references.scenes.Add(sphere.scene); references.spheres.Add(sphere); } public override Decision Check() { if (Plugin.slotSave.ActivatedSpheres.TryGetValue(_sphere, out bool value)) { return value ? Decision.Yes : Decision.No; } else { return Decision.Maybe; } } public override string ToString() { return $"Sphere{_sphere}"; } } public class FullGardenRequirement : Requirement { public override Decision Check() { return GameManager.MandalaManager.PlacedGodCubes.Count == 6 ? Decision.Yes : Decision.No; } public override string ToString() { return "FullGarden"; } } public class InvertedRequirement : Requirement { private readonly Requirement _requirement; public InvertedRequirement(Requirement requirement) { _requirement = requirement; references = requirement.references; } public override Decision Check() { Decision subdec = _requirement.Check(); if (subdec == Decision.Yes) { return Decision.No; } else if (subdec == Decision.No) { return Decision.Yes; } else { return Decision.Maybe; } } public override string ToString() { return $"Not({_requirement})"; } } }