public TronicSequence(N8Tronic Initial, NodeType InitialOut = NodeType.FlowOutA)
 {
     data = new List<DataBlock>();
     tronics = new N8BlockFactory();
     CurrentTronic = (FlowTronic)Initial;
     CurrentOut = Initial.GetNode(InitialOut);
     sequence = new List<FlowTronic>();
     Branches = new Stack<Tuple<FlowTronic, Node>>();
 }
        public bool IsCompatible(Node other)
        {
            //At the node-node level, all we can check is that DataIn or DataOut goes to DataBlock and that
            //FlowIn goes to FlowOut

            //First we make sure that we're not related to the same owner. Incest is not allowed!
            //We can't trust IDs any more, so let's figure it out another way.
            if (this.Owner.Equals(other))
            {
                throw new Exception("Invalid wiring! From tronic " + this.Owner.ID + " to itself!");
            }

            //Then some business logic hooray!
            if (this.Type == NodeType.FlowIn)
            {
                if ((other.Type == NodeType.FlowOutA) || (other.Type == NodeType.FlowOutB))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            if ((this.Type == NodeType.DataBlock))
            {
                //Kinda hacky, but it reads much better than a bunch of ors.
                if ((other.Type >= NodeType.DataInA) && (other.Type <= NodeType.DataOutB))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

            //The following is a neat trick I just figured out - we don't have to duplicate that logic going the other way,
            //we just check to make sure that the other node is one of the checked types and return what it thinks.

            if ( (other.Type != NodeType.FlowIn) && (other.Type != NodeType.DataBlock) )
            {
                throw new Exception("Invalid wiring! From a flow in or data block node to a flow out or data block node!");
            }

            //And now we're guaranteed to return something - the other side must be either a FlowIn or a DataBlock.
            return other.IsCompatible(this);
        }
        private void Append(FlowTronic NextTronic, Node NextOut)
        {
            if (CurrentTronic != null)
            {

                NextTronic.FlowInFrom(CurrentTronic, CurrentOut);
            }
            CurrentTronic = NextTronic;
            CurrentOut = NextOut;
            sequence.Add(NextTronic);
        }
        protected TronicSequence Target(string name = "Target")
        {
            Target p = tronics.Target(name);
            CurrentTronic = p;
            CurrentOut = p.GetNode(NodeType.FlowOutA);
            sequence.Add(p);

            return this;
        }
        protected TronicSequence Proxy(string name = "Proxy")
        {
            Proxy p = tronics.Proxy(name);
            CurrentTronic = p;
            CurrentOut = p.GetNode(NodeType.FlowOutA);
            sequence.Add(p);

            return this;
        }
        protected TronicSequence Keyboard(DataNodeOut Out, string name = "Keyboard")
        {
            Keyboard k = tronics.Keyboard(name);
            k.DataOutA(Out);
            CurrentTronic = k;
            CurrentOut = k.GetNode(NodeType.FlowOutA);
            sequence.Add(k);

            return this;
        }
        protected TronicSequence CoinVendInit(string name = "CoinVend")
        {
            CoinVend c = tronics.CoinVend(name);
            CurrentTronic = c;
            CurrentOut = c.GetNode(NodeType.FlowOutB);
            sequence.Add(c);

            return this;
        }
        protected TronicSequence Button(int type = 1, string name = "Button")
        {
            Button b = tronics.Button(type, name);
            CurrentTronic = b;
            CurrentOut = b.GetNode(NodeType.FlowOutA);
            sequence.Add(b);

            return this;
        }
        public TronicSequence Append(TronicSequence other)
        {
            if (this.CurrentTronic != null)
            {
                other.GetFirst().FlowInFrom(this.CurrentTronic, CurrentOut);
            }
            Tuple<FlowTronic, Node> temp = other.GetCurrent();

            this.CurrentTronic = temp.Item1;
            this.CurrentOut = temp.Item2;

            this.sequence.AddRange(other.sequence);
            this.data.AddRange(other.data);

            this.tronics.CopyFromDestructive(other.tronics);
            return this;
        }
        public virtual void WireTo(Node myNode, Node otherNode)
        {
            //We just silently ignore requests to wire to null - this makes things a lot easier later on.
            if (otherNode == null)
            {
                return;
            }

            Wire temp = new Wire(myNode, otherNode);
            this.WireTo(temp);
        }
 public virtual void FlowInFrom(FlowTronic other, Node which)
 {
     other.FlowOutTo(this, which.Type);
 }