diff --git a/Assets/Scripts/UI/UIGate.cs b/Assets/Scripts/UI/UIGate.cs index b6f05ab..c881c7c 100755 --- a/Assets/Scripts/UI/UIGate.cs +++ b/Assets/Scripts/UI/UIGate.cs @@ -26,8 +26,8 @@ namespace UntitledLogicGame.UI var subimage = GetComponentInChildren(); subimage.sprite = sprite; subimage.GetComponent().sizeDelta = new Vector2(100f, 100 * sprite.rect.width / 700f); // TODO get max width from UIManager - gameObject.name = "UI_" + _gatePrefab.GateType.ToString(); - GetComponentInChildren().text = _gatePrefab.GateType.ToString(); + gameObject.name = "UI_" + _gatePrefab.Definition.Name; + GetComponentInChildren().text = _gatePrefab.Definition.Name; } } @@ -36,7 +36,6 @@ namespace UntitledLogicGame.UI #region Private Properties private Gate _gatePrefab; - private RectTransform _rectTransform; #endregion diff --git a/Assets/Scripts/Workspace/Gate.cs b/Assets/Scripts/Workspace/Gate.cs index e34ead8..5f6207c 100755 --- a/Assets/Scripts/Workspace/Gate.cs +++ b/Assets/Scripts/Workspace/Gate.cs @@ -10,7 +10,6 @@ namespace UntitledLogicGame.Workspace { #region Unity Properties - public bool HasState; public GateType GateType; #endregion @@ -71,7 +70,7 @@ namespace UntitledLogicGame.Workspace private void Start() { - Utils.RandomName(GateType.ToString(), gameObject); + Utils.RandomName(Definition.Name, gameObject); } // Update is called once per frame @@ -91,7 +90,7 @@ namespace UntitledLogicGame.Workspace public bool HasInputAnchor(Anchor target) { - return !HasState && ( + return !Definition.HasState && ( InputAnchors.Contains(target) || InputAnchors.Any(a => a.HasInputAnchor(target)) ); diff --git a/Assets/Scripts/Workspace/GateDefinition.cs b/Assets/Scripts/Workspace/GateDefinition.cs deleted file mode 100755 index 6b7c7c4..0000000 --- a/Assets/Scripts/Workspace/GateDefinition.cs +++ /dev/null @@ -1,263 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace UntitledLogicGame.Workspace.Gates -{ - public enum GateType - { - // 000 Technical - NONE = 000, - // 100 Special - IN = 100, - OUT = 110, - // 200 Basic - BUF = 200, - AND = 210, - OR = 220, - XOR = 230, - // 300 Inverted Basic - NOT = 300, - NAND = 310, - NOR = 320, - XNOR = 330, - } - - public abstract class GateDefinition - { - private static Dictionary Definitions; - public abstract string[] Inputs { get; } - public abstract string[] Outputs { get; } - internal abstract Dictionary TruthTable { get; } - - private static void LoadAll() - { - Definitions = new Dictionary(); - foreach (var gateType in Enum.GetValues(typeof(GateType)).Cast()) - { - try - { - Type t = Type.GetType($"{typeof(GateDefinition).Namespace}.{gateType}Gate", true); - Definitions[gateType] = (GateDefinition)t.GetConstructor(new Type[0]).Invoke(new object[0]); - } - catch - { - Definitions[gateType] = (GateDefinition)typeof(NoneGate).GetConstructor(new Type[0]).Invoke(new object[0]); - } - - } - } - - public static GateDefinition Get(GateType gateType, Gate gate) - { - if (Definitions == null) - LoadAll(); - - GateDefinition definition = Definitions[gateType]; - - foreach (var inputName in definition.Inputs) - { - if(!gate.InputAnchors.Any(a => a.Name.Equals(inputName))) - throw new InvalidOperationException($"Gate has no {inputName} input anchor"); - } - - foreach (var outputName in definition.Outputs) - { - if (!gate.OutputAnchors.Any(a => a.Name.Equals(outputName))) - throw new InvalidOperationException($"Gate has no {outputName} output anchor"); - } - - return definition; - } - - internal GateDefinition() - { - foreach(var key in TruthTable.Keys) - { - if (key.Length != Inputs.Length) - throw new InvalidOperationException($"{GetType()} invalid inputs ({key})"); - } - if(Inputs.Length != 0) - { - foreach (var key in Utils.AllBoolArrayValues(Inputs.Length).Select(b => new State(b))) - { - if (!TruthTable.Keys.Contains(key)) - throw new InvalidOperationException($"{GetType()} no outputs for ({key})"); - var values = TruthTable[key]; - if (values.Length != Outputs.Length) - throw new InvalidOperationException($"{GetType()} invalid outputs for ({key})"); - } - } - } - - public bool[] GetState(Gate gate) - { - return Inputs.Select(i => gate.InputAnchors.First(a => a.Name.Equals(i)).Activated).ToArray(); - } - - public void Compute(Gate gate) - { - if(TruthTable.Count > 0) - { - State key = new State(GetState(gate)); - bool[] values = TruthTable[key].values; - foreach (var output in Outputs.Select((value, i) => new { i, value })) - { - gate.OutputAnchors.First(a => a.Name.Equals(output.value)).Activated = values[output.i]; - } - } - } - } - - internal class State - { - internal int Length => values.Length; - - internal bool[] values; - - public State(IEnumerable args) - { - values = args.ToArray(); - } - - public State(params bool[] args) - { - values = args; - } - - public override bool Equals(object obj) - { - return obj is State state && Enumerable.SequenceEqual(values, state.values); - } - - public override int GetHashCode() - { - //https://stackoverflow.com/questions/6832139/gethashcode-from-booleans-only - int hash = 17; - for (int index = 0; index < values.Length; index++) - hash = hash * 23 + values[index].GetHashCode(); - return hash; - } - - public override string ToString() - { - return string.Join(",", values); - } - } - - #region Gates - - internal class NoneGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { }; - public override string[] Outputs { get; } = new string[] { }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - }; - } - - internal class BufferGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { "A" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false ), new State( false ) }, - { new State( true ), new State( true ) }, - }; - } - - internal class NOTGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { "A" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false ), new State( true ) }, - { new State( true ), new State( false ) }, - }; - } - - internal class ANDGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { "A", "B" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false, false ), new State( false ) }, - { new State( false, true ), new State( false ) }, - { new State( true, false ), new State( false ) }, - { new State( true, true ), new State( true ) }, - }; - } - - internal class ORGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { "A", "B" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false, false ), new State( false ) }, - { new State( false, true ), new State( true ) }, - { new State( true, false ), new State( true ) }, - { new State( true, true ), new State( true ) }, - }; - } - - internal class XORGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { "A", "B" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false, false ), new State( false ) }, - { new State( false, true ), new State( true ) }, - { new State( true, false ), new State( true ) }, - { new State( true, true ), new State( false ) }, - }; - } - - internal class NANDGate : GateDefinition - { - public override string[] Inputs { get; } = new string[]{ "A", "B" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false, false ), new State( true ) }, - { new State( false, true ), new State( true ) }, - { new State( true, false ), new State( true ) }, - { new State( true, true ), new State( false ) }, - }; - } - - internal class NORGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { "A", "B" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false, false ), new State( true ) }, - { new State( false, true ), new State( false ) }, - { new State( true, false ), new State( false ) }, - { new State( true, true ), new State( false ) }, - }; - } - - internal class XNORGate : GateDefinition - { - public override string[] Inputs { get; } = new string[] { "A", "B" }; - public override string[] Outputs { get; } = new string[] { "Q" }; - internal override Dictionary TruthTable { get; } = new Dictionary - { - { new State( false, false ), new State( true ) }, - { new State( false, true ), new State( false ) }, - { new State( true, false ), new State( false ) }, - { new State( true, true ), new State( true ) }, - }; - } - - #endregion -} diff --git a/Assets/Scripts/Workspace/Gates.meta b/Assets/Scripts/Workspace/Gates.meta new file mode 100755 index 0000000..7d3bf31 --- /dev/null +++ b/Assets/Scripts/Workspace/Gates.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 28d635657f6056543894c99d2d021d36 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Workspace/Gates/GateDefinition.cs b/Assets/Scripts/Workspace/Gates/GateDefinition.cs new file mode 100755 index 0000000..8a66032 --- /dev/null +++ b/Assets/Scripts/Workspace/Gates/GateDefinition.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace UntitledLogicGame.Workspace.Gates +{ + public abstract class GateDefinition + { + private static Dictionary Definitions; + internal static Dictionary EmptyTruthTable = new Dictionary(); + public abstract string[] Inputs { get; } + public abstract string[] Outputs { get; } + internal abstract Dictionary TruthTable { get; } + public string Name { get; internal set; } + public bool HasState { get; } = false; + public GateDefinition New => (GateDefinition)GetType().GetConstructor(new Type[0]).Invoke(new object[0]); + + private static void LoadAll() + { + Definitions = new Dictionary(); + foreach (var gateType in Enum.GetValues(typeof(GateType)).Cast()) + { + try + { + Type t = Type.GetType($"{typeof(GateDefinition).Namespace}.{gateType}Gate", true); + Definitions[gateType] = (GateDefinition)t.GetConstructor(new Type[0]).Invoke(new object[0]); + Definitions[gateType].Name = gateType.ToString(); + } + catch + { + Definitions[gateType] = (GateDefinition)typeof(NoneGate).GetConstructor(new Type[0]).Invoke(new object[0]); + Definitions[gateType].Name = gateType.ToString(); + } + } + } + + public static GateDefinition Get(GateType gateType, Gate gate) + { + if (Definitions == null) + LoadAll(); + + GateDefinition definition = Definitions[gateType]; + + foreach (var inputName in definition.Inputs) + { + if(!gate.InputAnchors.Any(a => a.Name.Equals(inputName))) + throw new InvalidOperationException($"Gate has no {inputName} input anchor"); + } + + foreach (var outputName in definition.Outputs) + { + if (!gate.OutputAnchors.Any(a => a.Name.Equals(outputName))) + throw new InvalidOperationException($"Gate has no {outputName} output anchor"); + } + + if (definition.HasState) + return definition.New; + else + return definition; + } + + internal GateDefinition() + { + foreach(var key in TruthTable.Keys) + { + if (key.Length != Inputs.Length) + throw new InvalidOperationException($"{GetType()} invalid inputs ({key})"); + } + if(Inputs.Length != 0) + { + foreach (var key in Utils.AllBoolArrayValues(Inputs.Length).Select(b => new InputState(b))) + { + if (!TruthTable.Keys.Contains(key)) + throw new InvalidOperationException($"{GetType()} no outputs for ({key})"); + var values = TruthTable[key]; + if (values.Length != Outputs.Length) + throw new InvalidOperationException($"{GetType()} invalid outputs for ({key})"); + } + } + } + + public bool[] GetState(Gate gate) + { + return Inputs.Select(i => gate.InputAnchors.First(a => a.Name.Equals(i)).Activated).ToArray(); + } + + public void Compute(Gate gate) + { + InputState input = new InputState(GetState(gate)); + State output = Compute(input); + foreach (var outputAnchor in Outputs.Select((name, i) => new { i, name })) + gate.OutputAnchors.First(a => a.Name.Equals(outputAnchor.name)).Activated = output[outputAnchor.i]; + } + + internal OutputState Compute(InputState input) + { + if (TruthTable.Count > 0) + { + return TruthTable[input]; + } + else + { + return new OutputState(0); + } + } + } +} diff --git a/Assets/Scripts/Workspace/GateDefinition.cs.meta b/Assets/Scripts/Workspace/Gates/GateDefinition.cs.meta similarity index 83% rename from Assets/Scripts/Workspace/GateDefinition.cs.meta rename to Assets/Scripts/Workspace/Gates/GateDefinition.cs.meta index c88f1d0..de51929 100755 --- a/Assets/Scripts/Workspace/GateDefinition.cs.meta +++ b/Assets/Scripts/Workspace/Gates/GateDefinition.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d351d9e762a4bc64c8491ae8fabcdede +guid: 177f93d9946e90d4b863f2fcbdc743c8 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/Scripts/Workspace/Gates/GateDefinitionList.cs b/Assets/Scripts/Workspace/Gates/GateDefinitionList.cs new file mode 100755 index 0000000..a5e47cf --- /dev/null +++ b/Assets/Scripts/Workspace/Gates/GateDefinitionList.cs @@ -0,0 +1,300 @@ +using System.Collections.Generic; + +namespace UntitledLogicGame.Workspace.Gates +{ + #region 000 - Technical + + internal class NoneGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { }; + public override string[] Outputs { get; } = new string[] { }; + internal override Dictionary TruthTable => EmptyTruthTable; + } + + #endregion + + #region 100 - Special + + #endregion + + #region 200 - Basic + + internal class BufferGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false ), new OutputState( false ) }, + { new InputState( true ), new OutputState( true ) }, + }; + } + + internal class ANDGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A", "B" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false, false ), new OutputState( false ) }, + { new InputState( false, true ), new OutputState( false ) }, + { new InputState( true, false ), new OutputState( false ) }, + { new InputState( true, true ), new OutputState( true ) }, + }; + } + + internal class ORGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A", "B" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false, false ), new OutputState( false ) }, + { new InputState( false, true ), new OutputState( true ) }, + { new InputState( true, false ), new OutputState( true ) }, + { new InputState( true, true ), new OutputState( true ) }, + }; + } + + internal class XORGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A", "B" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false, false ), new OutputState( false ) }, + { new InputState( false, true ), new OutputState( true ) }, + { new InputState( true, false ), new OutputState( true ) }, + { new InputState( true, true ), new OutputState( false ) }, + }; + } + + #endregion + + #region 300 - Inverted Basic + + internal class NOTGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false ), new OutputState( true ) }, + { new InputState( true ), new OutputState( false ) }, + }; + } + + internal class NANDGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A", "B" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false, false ), new OutputState( true ) }, + { new InputState( false, true ), new OutputState( true ) }, + { new InputState( true, false ), new OutputState( true ) }, + { new InputState( true, true ), new OutputState( false ) }, + }; + } + + internal class NORGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A", "B" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false, false ), new OutputState( true ) }, + { new InputState( false, true ), new OutputState( false ) }, + { new InputState( true, false ), new OutputState( false ) }, + { new InputState( true, true ), new OutputState( false ) }, + }; + } + + internal class XNORGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "A", "B" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable { get; } = new Dictionary + { + { new InputState( false, false ), new OutputState( true ) }, + { new InputState( false, true ), new OutputState( false ) }, + { new InputState( true, false ), new OutputState( false ) }, + { new InputState( true, true ), new OutputState( true ) }, + }; + } + + #endregion + + #region 400 - Latches + + internal class SRLatchGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "S", "R" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable => EmptyTruthTable; + public new string Name => "SR Latch"; + public new bool HasState => true; + + private bool _q; + + internal new OutputState Compute(InputState input) + { + bool s = input[0]; + bool r = input[1]; + if (r) + _q = false; + else if (s) + _q = true; + return new OutputState(_q); + } + } + + internal class JKLatchGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "J", "K" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable => EmptyTruthTable; + public new string Name => "JK Latch"; + public new bool HasState => true; + + private bool _q; + + internal new OutputState Compute(InputState input) + { + bool j = input[0]; + bool k = input[1]; + if (k && j) + _q = !_q; + else if (k) + _q = false; + else if (j) + _q = true; + return new OutputState(_q); + } + } + + internal class DLatchGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "D", "E" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable => EmptyTruthTable; + public new string Name => "D Latch"; + public new bool HasState => true; + + private bool _q; + + internal new OutputState Compute(InputState input) + { + bool d = input[0]; + bool e = input[1]; + if (e) + _q = d; + return new OutputState(_q); + } + } + + #endregion + + #region 500 - Flip-Flops + + internal class SRFlipFlopGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "S", "R", "CLK" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable => EmptyTruthTable; + public new string Name => "SR Flip-Flop"; + public new bool HasState => true; + + private bool _q; + private bool _lastClk; + + internal new OutputState Compute(InputState input) + { + bool s = input[0]; + bool r = input[1]; + bool clk = input[2]; + if (clk && !_lastClk) // rising edge + if (r) + _q = false; + else if (s) + _q = true; + _lastClk = clk; + return new OutputState(_q); + } + } + + internal class JKFlipFlopGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "J", "K", "CLK" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable => EmptyTruthTable; + public new string Name => "JK Flip-Flop"; + public new bool HasState => true; + + private bool _q; + private bool _lastClk; + + internal new OutputState Compute(InputState input) + { + bool j = input[0]; + bool k = input[1]; + bool clk = input[2]; + if (clk && !_lastClk) // rising edge + if (k && j) + _q = !_q; + else if (k) + _q = false; + else if (j) + _q = true; + _lastClk = clk; + return new OutputState(_q); + } + } + + internal class DFlipFlopGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "D", "CLK" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable => EmptyTruthTable; + public new string Name => "D Flip-Flop"; + public new bool HasState => true; + + private bool _q; + private bool _lastClk; + + internal new OutputState Compute(InputState input) + { + bool d = input[0]; + bool clk = input[1]; + if (clk && !_lastClk) // rising edge + _q = d; + _lastClk = clk; + return new OutputState(_q); + } + } + + internal class TFlipFlopGate : GateDefinition + { + public override string[] Inputs { get; } = new string[] { "T", "CLK" }; + public override string[] Outputs { get; } = new string[] { "Q" }; + internal override Dictionary TruthTable => EmptyTruthTable; + public new string Name => "T Flip-Flop"; + public new bool HasState => true; + + private bool _q; + private bool _lastClk; + + internal new OutputState Compute(InputState input) + { + bool t = input[0]; + bool clk = input[1]; + if (clk && !_lastClk) // rising edge + if (t) + _q = !_q; + _lastClk = clk; + return new OutputState(_q); + } + } + + #endregion +} diff --git a/Assets/Scripts/Workspace/Gates/GateDefinitionList.cs.meta b/Assets/Scripts/Workspace/Gates/GateDefinitionList.cs.meta new file mode 100755 index 0000000..ec1e295 --- /dev/null +++ b/Assets/Scripts/Workspace/Gates/GateDefinitionList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fdbb8b9c639517440a7c57882d954ef1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Workspace/Gates/GateType.cs b/Assets/Scripts/Workspace/Gates/GateType.cs new file mode 100755 index 0000000..e00c8d6 --- /dev/null +++ b/Assets/Scripts/Workspace/Gates/GateType.cs @@ -0,0 +1,30 @@ +namespace UntitledLogicGame.Workspace.Gates +{ + public enum GateType + { + // 000 - Technical + NONE = 000, + // 100 - Special + IN = 100, + OUT = 110, + // 200 - Basic + BUF = 200, + AND = 210, + OR = 220, + XOR = 230, + // 300 - Inverted Basic + NOT = 300, + NAND = 310, + NOR = 320, + XNOR = 330, + // 400 - Latches + SRLatch = 400, + JKLatch = 410, + DLatch = 420, + // 500 - Flip-Flops + SRFlipFlop = 500, + JKFlipFlop = 510, + DFlipFlop = 520, + TFlipFlop = 530 + } +} diff --git a/Assets/Scripts/Workspace/Gates/GateType.cs.meta b/Assets/Scripts/Workspace/Gates/GateType.cs.meta new file mode 100755 index 0000000..8749839 --- /dev/null +++ b/Assets/Scripts/Workspace/Gates/GateType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4619035df28c4374498d0bafc176449e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Workspace/Gates/State.cs b/Assets/Scripts/Workspace/Gates/State.cs new file mode 100755 index 0000000..67605bf --- /dev/null +++ b/Assets/Scripts/Workspace/Gates/State.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Linq; + +namespace UntitledLogicGame.Workspace.Gates +{ + internal class InputState : State + { + public InputState(IEnumerable args) : base(args) { } + + public InputState(params bool[] args) : base(args) { } + + public InputState(int len) : base(len) { } + } + + internal class OutputState : State + { + public OutputState(IEnumerable args) : base(args) { } + + public OutputState(params bool[] args) : base(args) { } + + public OutputState(int len) : base(len) { } + } + + internal abstract class State + { + internal int Length => values.Length; + + internal bool[] values; + + public State(IEnumerable args) + { + values = args.ToArray(); + } + + public State(params bool[] args) + { + values = args; + } + + public State(int len) + { + values = new bool[len]; + } + + public bool this[int index] + { + get + { + if (index < 0 || index >= values.Length) + return false; + return values[index]; + } + set + { + if (index >= 0 && index < values.Length) + values[index] = value; + } + } + + public override bool Equals(object obj) + { + return obj is State state && Enumerable.SequenceEqual(values, state.values); + } + + public override int GetHashCode() + { + //https://stackoverflow.com/questions/6832139/gethashcode-from-booleans-only + int hash = 17; + for (int index = 0; index < values.Length; index++) + hash = hash * 23 + values[index].GetHashCode(); + return hash; + } + + public override string ToString() + { + return string.Join(",", values); + } + } +} diff --git a/Assets/Scripts/Workspace/Gates/State.cs.meta b/Assets/Scripts/Workspace/Gates/State.cs.meta new file mode 100755 index 0000000..34a268b --- /dev/null +++ b/Assets/Scripts/Workspace/Gates/State.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae92d013688882845845e2ed4cba3896 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/TODO.txt b/TODO.txt index f910f64..6139a8d 100755 --- a/TODO.txt +++ b/TODO.txt @@ -1,6 +1,8 @@ TODO -(0) mux/demux +-(2) gate bar sub categories -(2) named anchors +-(3) clocks (1Hz, 5Hz, 10Hz, etc.) -(3) generic rect gates -(3) state gates -(3) cable overlap (same/diff circuit)