more gates definition + refactoring
This commit is contained in:
@@ -26,8 +26,8 @@ namespace UntitledLogicGame.UI
|
|||||||
var subimage = GetComponentInChildren<SVGImage>();
|
var subimage = GetComponentInChildren<SVGImage>();
|
||||||
subimage.sprite = sprite;
|
subimage.sprite = sprite;
|
||||||
subimage.GetComponent<RectTransform>().sizeDelta = new Vector2(100f, 100 * sprite.rect.width / 700f); // TODO get max width from UIManager
|
subimage.GetComponent<RectTransform>().sizeDelta = new Vector2(100f, 100 * sprite.rect.width / 700f); // TODO get max width from UIManager
|
||||||
gameObject.name = "UI_" + _gatePrefab.GateType.ToString();
|
gameObject.name = "UI_" + _gatePrefab.Definition.Name;
|
||||||
GetComponentInChildren<TextMeshProUGUI>().text = _gatePrefab.GateType.ToString();
|
GetComponentInChildren<TextMeshProUGUI>().text = _gatePrefab.Definition.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +36,6 @@ namespace UntitledLogicGame.UI
|
|||||||
#region Private Properties
|
#region Private Properties
|
||||||
|
|
||||||
private Gate _gatePrefab;
|
private Gate _gatePrefab;
|
||||||
private RectTransform _rectTransform;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ namespace UntitledLogicGame.Workspace
|
|||||||
{
|
{
|
||||||
#region Unity Properties
|
#region Unity Properties
|
||||||
|
|
||||||
public bool HasState;
|
|
||||||
public GateType GateType;
|
public GateType GateType;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -71,7 +70,7 @@ namespace UntitledLogicGame.Workspace
|
|||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
Utils.RandomName(GateType.ToString(), gameObject);
|
Utils.RandomName(Definition.Name, gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update is called once per frame
|
// Update is called once per frame
|
||||||
@@ -91,7 +90,7 @@ namespace UntitledLogicGame.Workspace
|
|||||||
|
|
||||||
public bool HasInputAnchor(Anchor target)
|
public bool HasInputAnchor(Anchor target)
|
||||||
{
|
{
|
||||||
return !HasState && (
|
return !Definition.HasState && (
|
||||||
InputAnchors.Contains(target) ||
|
InputAnchors.Contains(target) ||
|
||||||
InputAnchors.Any(a => a.HasInputAnchor(target))
|
InputAnchors.Any(a => a.HasInputAnchor(target))
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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<GateType, GateDefinition> Definitions;
|
|
||||||
public abstract string[] Inputs { get; }
|
|
||||||
public abstract string[] Outputs { get; }
|
|
||||||
internal abstract Dictionary<State, State> TruthTable { get; }
|
|
||||||
|
|
||||||
private static void LoadAll()
|
|
||||||
{
|
|
||||||
Definitions = new Dictionary<GateType, GateDefinition>();
|
|
||||||
foreach (var gateType in Enum.GetValues(typeof(GateType)).Cast<GateType>())
|
|
||||||
{
|
|
||||||
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<bool> 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class BufferGate : GateDefinition
|
|
||||||
{
|
|
||||||
public override string[] Inputs { get; } = new string[] { "A" };
|
|
||||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
|
||||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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<State, State> TruthTable { get; } = new Dictionary<State, State>
|
|
||||||
{
|
|
||||||
{ 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
|
|
||||||
}
|
|
||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 28d635657f6056543894c99d2d021d36
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
+107
@@ -0,0 +1,107 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace UntitledLogicGame.Workspace.Gates
|
||||||
|
{
|
||||||
|
public abstract class GateDefinition
|
||||||
|
{
|
||||||
|
private static Dictionary<GateType, GateDefinition> Definitions;
|
||||||
|
internal static Dictionary<InputState, OutputState> EmptyTruthTable = new Dictionary<InputState, OutputState>();
|
||||||
|
public abstract string[] Inputs { get; }
|
||||||
|
public abstract string[] Outputs { get; }
|
||||||
|
internal abstract Dictionary<InputState, OutputState> 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<GateType, GateDefinition>();
|
||||||
|
foreach (var gateType in Enum.GetValues(typeof(GateType)).Cast<GateType>())
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: d351d9e762a4bc64c8491ae8fabcdede
|
guid: 177f93d9946e90d4b863f2fcbdc743c8
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
+300
@@ -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<InputState, OutputState> 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||||
|
{
|
||||||
|
{ 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<InputState, OutputState> 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<InputState, OutputState> 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<InputState, OutputState> 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<InputState, OutputState> 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<InputState, OutputState> 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<InputState, OutputState> 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<InputState, OutputState> 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
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fdbb8b9c639517440a7c57882d954ef1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Executable
+30
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4619035df28c4374498d0bafc176449e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Executable
+79
@@ -0,0 +1,79 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace UntitledLogicGame.Workspace.Gates
|
||||||
|
{
|
||||||
|
internal class InputState : State
|
||||||
|
{
|
||||||
|
public InputState(IEnumerable<bool> args) : base(args) { }
|
||||||
|
|
||||||
|
public InputState(params bool[] args) : base(args) { }
|
||||||
|
|
||||||
|
public InputState(int len) : base(len) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class OutputState : State
|
||||||
|
{
|
||||||
|
public OutputState(IEnumerable<bool> 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<bool> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ae92d013688882845845e2ed4cba3896
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
TODO
|
TODO
|
||||||
-(0) mux/demux
|
-(0) mux/demux
|
||||||
|
-(2) gate bar sub categories
|
||||||
-(2) named anchors
|
-(2) named anchors
|
||||||
|
-(3) clocks (1Hz, 5Hz, 10Hz, etc.)
|
||||||
-(3) generic rect gates
|
-(3) generic rect gates
|
||||||
-(3) state gates
|
-(3) state gates
|
||||||
-(3) cable overlap (same/diff circuit)
|
-(3) cable overlap (same/diff circuit)
|
||||||
|
|||||||
Reference in New Issue
Block a user