public void TestExecute_ReactiveChoicePresenter(IBlackboard blackboard, ContentUnit selectedCU, ContentUnit originalCU, ContentUnit[] choices)
        {
            blackboard.Clear();
            blackboard.AddUnit(selectedCU);
            blackboard.AddUnit(originalCU);
            blackboard.AddLink(originalCU, selectedCU, LinkTypes.L_SelectedContentUnit);

            foreach (ContentUnit choice in choices)
            {
                blackboard.AddUnit(choice);
                blackboard.AddLink(originalCU, choice, LinkTypes.L_Choice);
            }

            KS_Old_ReactiveChoicePresenter ks = new KS_Old_ReactiveChoicePresenter(blackboard);

            ks.PresenterExecute += GenerateEventHandler(selectedCU, choices, blackboard);

            var KSAs = ks.Precondition();

            int count = KSAs.Count();

            Assert.Equal(1, count);

            // Execute the activated choice presenter
            KSAs.ElementAt(0).Execute();
        }
        public void TestObviationCondition(IBlackboard blackboard, ReactiveKnowledgeSource ks, IUnit[] unitsToAdd)
        {
            blackboard.Clear(); // Clear the blackboard so that there aren't KUs laying around from previous tests.

            // Add the units in unitsToAdd
            foreach (IUnit unitToAdd in unitsToAdd)
            {
                blackboard.AddUnit(unitToAdd);
            }

            // Call KnowledgeSource.Precondition() to get the activated KSs.
            IEnumerable <IKnowledgeSourceActivation> KSAs = ks.Precondition();

            // If there are any activated KSs...
            if (KSAs.Any())
            {
                // First, the obviation condition should evaluate to false since the matching KUs are still on the blackboard.
                foreach (IKnowledgeSourceActivation KSA in KSAs)
                {
                    Assert.False(KSA.EvaluateObviationCondition());
                }

                // Second, remove the units from the blackboard
                foreach (IUnit unitToRemove in unitsToAdd)
                {
                    blackboard.RemoveUnit(unitToRemove);
                }

                // Finally, the obviation condition should now evaluate to true since the matching KUs are no longer on the blackboard.
                foreach (IKnowledgeSourceActivation KSA in KSAs)
                {
                    Assert.True(KSA.EvaluateObviationCondition());
                }
            }
        }
コード例 #3
0
 public static void AddUnits(IBlackboard blackboard, IUnit[] unitsToAdd)
 {
     foreach (IUnit unit in unitsToAdd)
     {
         Assert.True(blackboard.AddUnit(unit));
     }
 }
        private static Unit MakeRuleUnit(string ruleID, string pool, IBlackboard blackboard)
        {
            Unit u = new Unit();

            u.AddComponent(new KC_UnitID(ruleID, true));
            u.AddComponent(new KC_ContentPool(pool, true));
            blackboard.AddUnit(u);
            return(u);
        }
        /*
         * Useful methods for ProcessNode.
         */
        // fixme: consider pushing processing into a component on Units.
        public static void ActivateIDRequest(Unit node, IBlackboard blackboard)
        {
            Unit origNode = FindOriginalUnit(node, blackboard);

            origNode.SetActiveRequest(true);

            /*
             * Save a reference to the current tree node we're expanding on the blackboard.
             */
            Unit leafExpansionRef = new Unit();

            leafExpansionRef.AddComponent(new KC_UnitReference(CurrentTreeNodeExpansion, true, origNode));
            blackboard.AddUnit(leafExpansionRef);
        }
        public void TestPrecondition(IBlackboard blackboard, ReactiveKnowledgeSource ks, IUnit[] unitsToAdd, bool previouslyMatched, int numActivatedKSs)
        {
            blackboard.Clear(); // Clear the blackboard so that there aren't KUs laying around from previous tests.

            // Add the units in unitsToAdd
            foreach (IUnit unitToAdd in unitsToAdd)
            {
                blackboard.AddUnit(unitToAdd);
                // If they should be marked as previously matched, set KSPreconditionMatched
                if (previouslyMatched)
                {
                    unitToAdd.Slots[KSPreconditionMatched] = new HashSet <ReactiveKnowledgeSource> {
                        ks
                    };
                }
            }

            // Call KnowledgeSource.Precondition() to get the activated KSs.
            IEnumerable <IKnowledgeSourceActivation> KSAs = ks.Precondition();

            // Check that the number of activated KSs equals the number we're expecting
            int count = KSAs.Count();

            Assert.Equal(numActivatedKSs, count);

            /*
             * fixme: need to remove this because we're no longer storing matches on the matching units. Instead store match sets on the KnowledgeSources.
             * For now I've created a separate test for Selector Knowledge Sources (which already implement match set storage) until we get this
             * resolved for all KnowledgeSources.
             *
             * If there were activated KSs, check that the KUs were marked as having been matched.
             */
            if (count > 0)
            {
                foreach (IUnit u in unitsToAdd)
                {
                    Assert.True(u.Slots.ContainsKey(KSPreconditionMatched));
                    bool containsKS = ((HashSet <ReactiveKnowledgeSource>)u.Slots[KSPreconditionMatched]).Contains(ks);
                    Assert.True(containsKS);
                }
            }

            // Run the preconditions again to verify that on a second running they don't activate any KSs.
            KSAs  = ks.Precondition();
            count = KSAs.Count();
            Assert.Equal(0, count);
        }
コード例 #7
0
        /*
         * Utility method for copying a unit to a new content pool.
         */
        protected Unit CopyUnitToPool(Unit unit, string pool)
        {
            Unit newUnit = new Unit(unit);

            /*
             * If there is an existing content pool component remove the componenet before adding a new one with the new pool. The case in which there won't be a content pool
             * component is when copying from the global pool (no pool) into a pool.
             */
            if (newUnit.HasComponent <KC_ContentPool>())
            {
                newUnit.RemoveComponent(newUnit.GetComponent <KC_ContentPool>());
            }
            newUnit.AddComponent(new KC_ContentPool(pool, true));

            m_blackboard.AddUnit(newUnit);
            m_blackboard.AddLink(unit, newUnit, LinkTypes.L_SelectedUnit, true); // fixme: need a more general link type for copies between pools
            return(newUnit);
        }
        public CFGExpansionController(Unit rootNode, string grammarRulePool, IBlackboard blackboard)
        {
            this.blackboard = blackboard;

            RootNode = rootNode;

            /*
             * Replace with three filters: KS_SelectTreeLeaves, which creates a content pool containing all the tree leaves meeting some condition,
             * KS_ScheduledTierSelector, which, given a component with a sortable value, selects the lowest (in this case it will be order in which a leaf is added to tree), and
             * KS_ProcessTreeNode, which in this case will activate the ID request and save a reference to the node. KS_ScheduledTierSelector will become abstract, with
             * several children: KS_ScheduledHighestTierSelector, KS_ScheduledLowestTierSelector, KS_UniformTopNTierSelector, KS_UniformBottomNTierSelector,
             * KS_ExponentialDistTierSelector.
             * This decoupling allows other logic to be used in the choice of leaf to expand (such as computing a heuristic for picking a node to expand).
             */
            m_pickLeftmostNodeToExpand = new KS_ScheduledExecute(
                () =>
            {
                var nonTerminalLeafNodes = from Unit node in blackboard.LookupUnits <Unit>()
                                           where node.HasComponent <KC_TreeNode>() && node.IsTreeLeaf()
                                           where node.HasComponent <KC_IDSelectionRequest>()
                                           select node;

                if (nonTerminalLeafNodes.Any())
                {
                    nonTerminalLeafNodes.First().SetActiveRequest(true);

                    /*
                     * Save a reference to the current tree node we're expanding on the blackboard.
                     */
                    Unit leafExpansionRef = new Unit();
                    leafExpansionRef.AddComponent(new KC_UnitReference(CurrentTreeNodeExpansion, true, nonTerminalLeafNodes.First()));
                    blackboard.AddUnit(leafExpansionRef);
                }
            }
                );

            // string idOutputPool = "pool" + DateTime.Now.Ticks;
            string idOutputPool = "idOutputPool";

            m_lookupGrammarRules = new KS_ScheduledIDSelector(blackboard, grammarRulePool, idOutputPool);

            // string uniformDistOutputPool = "pool" + DateTime.Now.Ticks;
            string uniformDistOutputPool = "uniformDistOutputPool";

            m_chooseGrammarRule = new KS_ScheduledUniformDistributionSelector(blackboard, idOutputPool, uniformDistOutputPool, 1);

            /*
             * Replace with KS_ExpandTreeNode. An instance of KS_ExpandTreeNode has:
             * 1) The name of a content pool a unit with a decomposition.
             * 2) The name of a KC_UnitReference containing a pointer to the node to expand.
             */
            m_treeExpander = new KS_ScheduledExecute(
                () =>
            {
                var rule = from unit in blackboard.LookupUnits <Unit>()
                           where unit.HasComponent <KC_ContentPool>() && unit.ContentPoolEquals(uniformDistOutputPool)
                           select unit;

                /*
                 * Grab the reference to the current leaf node we're expanding.
                 */
                var nodeToExpandQuery = from unit in blackboard.LookupUnits <Unit>()
                                        where unit.HasComponent <KC_UnitReference>()
                                        select unit;
                Unit nodeToExpandRef = nodeToExpandQuery.First();

                if (rule.Any())
                {
                    Debug.Assert(rule.Count() == 1);              // Only one rule is picked to expand a symbol

                    Debug.Assert(nodeToExpandQuery.Count() == 1); // Should be only one reference we're expanding.

                    Unit selectedRule = rule.First();
                    Unit ruleNode     = new Unit(selectedRule);
                    // Remove the KC_Decomposition (not needed) and KC_ContentPool (will cause node to be prematurely cleaned up) components
                    ruleNode.RemoveComponent(ruleNode.GetComponent <KC_Decomposition>());
                    ruleNode.RemoveComponent(ruleNode.GetComponent <KC_ContentPool>());

                    // fixme: consider defining conversion operators so this looks like
                    // new KC_TreeNode((KC_TreeNode)nodeToExpand);
                    ruleNode.AddComponent(new KC_TreeNode(nodeToExpandRef.GetUnitReference().GetComponent <KC_TreeNode>()));
                    blackboard.AddUnit(ruleNode);

                    // For each of the Units in the decomposition, add them to the tree as children of ruleCopy.
                    foreach (Unit child in selectedRule.GetDecomposition())
                    {
                        // Make a copy of Unit in the decomposition and add it to the tree.
                        Unit childNode = new Unit(child);
                        blackboard.AddUnit(childNode);
                        childNode.AddComponent(new KC_TreeNode(ruleNode.GetComponent <KC_TreeNode>()));
                    }
                }
                else
                {
                    // No rule was found. Create a pseudo-decomposition consisting of just the TargetUnitID in ## (borrowing from Tracery).
                    Unit noRuleTextDecomp = new Unit();
                    noRuleTextDecomp.AddComponent(new KC_TreeNode(nodeToExpandRef.GetUnitReference().GetComponent <KC_TreeNode>()));
                    noRuleTextDecomp.AddComponent(new KC_Text("#" + nodeToExpandRef.GetUnitReference().GetTargetUnitID() + "#", true));
                    blackboard.AddUnit(noRuleTextDecomp);
                }
                blackboard.RemoveUnit(nodeToExpandRef);     // Remove the reference to the leaf node to expand (it has been expanded).
            }
                );

            m_cleanSelectionPools = new KS_ScheduledFilterPoolCleaner(blackboard, new string[] { idOutputPool, uniformDistOutputPool });

            bool GenSequencePrecond()
            {
                var leafNodes = from Unit node in blackboard.LookupUnits <Unit>()
                                where node.HasComponent <KC_TreeNode>() && node.IsTreeLeaf()
                                select node;

                // This is ready to run if no leaf node contains a KC_IDSelectionRequest component (meaning it's a non-terminal).
                return(leafNodes.All(node => !node.HasComponent <KC_IDSelectionRequest>()));
            }

            /*
             * Replace with KS_LinearizeTreeLeaves.
             */
            void GenSequenceExec()
            {
                // Walk the tree to find the leafs from left to right.
                IList <Unit> leafs = new List <Unit>();

                AddLeafs(RootNode, leafs);

                // Write out the leafs of the generated tree
                foreach (Unit leaf in leafs)
                {
                    Console.Write(leaf.GetText() + " ");
                }

                // Delete the tree.
                var treeNodes = from Unit node in blackboard.LookupUnits <Unit>()
                                where node.HasComponent <KC_TreeNode>()
                                select node;

                foreach (var node in treeNodes)
                {
                    blackboard.RemoveUnit(node);
                }
            }

            m_addGeneratedSequence = new KS_ScheduledExecute(GenSequenceExec, GenSequencePrecond);
        }
        public static void Demo1_KC_DefineUnits(IBlackboard blackboard)
        {
            Unit start = new Unit();

            start.AddComponent(new KC_UnitID("start", true));
            start.AddComponent(new KC_Text("You stand before an old wooden door.", true));

            Unit start_Choice1 = new Unit();

            start_Choice1.AddComponent(new KC_IDSelectionRequest("open door", true));
            start_Choice1.AddComponent(new KC_Text("Open the door", true));

            Unit start_Choice2 = new Unit();

            start_Choice2.AddComponent(new KC_IDSelectionRequest("wait", true));
            start_Choice2.AddComponent(new KC_Text("Wait", true));

            Unit openDoor = new Unit();

            openDoor.AddComponent(new KC_UnitID("open door", true));
            openDoor.AddComponent(new KC_Text("Opening the door, you step forth into adventure.", true));

            Unit waited = new Unit();

            waited.AddComponent(new KC_UnitID("wait", true));
            waited.AddComponent(new KC_Text("You wait fruitlessly in front the door.", true));

            Unit waitedChoice1 = new Unit();

            waitedChoice1.AddComponent(new KC_IDSelectionRequest("waited again", true));
            waitedChoice1.AddComponent(new KC_Text("Wait again", true));

            Unit waitedChoice2 = new Unit();

            waitedChoice2.AddComponent(new KC_IDSelectionRequest("open door after waiting", true));
            waitedChoice2.AddComponent(new KC_Text("Finally open the door", true));

            Unit waitedAgain = new Unit();

            waitedAgain.AddComponent(new KC_UnitID("waited again", true));
            waitedAgain.AddComponent(new KC_Text("Sunk in a deep malaise, you wait the rest of your life.", true));

            Unit openDoorAfterWaiting = new Unit();

            openDoorAfterWaiting.AddComponent(new KC_UnitID("open door after waiting", true));
            openDoorAfterWaiting.AddComponent(new KC_Text("Breaking through your reservations, you step forward into a life of adventure.", true));

            blackboard.AddUnit(start);
            blackboard.AddUnit(start_Choice1);
            blackboard.AddUnit(start_Choice2);
            blackboard.AddUnit(openDoor);
            blackboard.AddUnit(waited);
            blackboard.AddUnit(waitedChoice1);
            blackboard.AddUnit(waitedChoice2);
            blackboard.AddUnit(waitedAgain);
            blackboard.AddUnit(openDoorAfterWaiting);

            blackboard.AddLink(start, start_Choice1, LinkTypes.L_Choice);
            blackboard.AddLink(start, start_Choice2, LinkTypes.L_Choice);
            blackboard.AddLink(waited, waitedChoice1, LinkTypes.L_Choice);
            blackboard.AddLink(waited, waitedChoice2, LinkTypes.L_Choice);
        }
        public static void DemoEnsemble_DefineUnits(IBlackboard blackboard)
        {
            Unit rule = new Unit();

            rule.AddComponent(new KC_UnitID("If you haven't said hello, you're likely to say hello.", true));
            rule.AddComponent(new KC_IDSelectionRequest("greeting", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "\\+ saidHello.", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you've already said hello, less likely to do it again.", true));
            rule.AddComponent(new KC_IDSelectionRequest("greeting", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "saidHello.", true));
            rule.AddComponent(new KC_Utility(-5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you've already said hello, you are more likely to ask how they have been doing.", true));
            rule.AddComponent(new KC_IDSelectionRequest("askDay", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "saidHello.", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you've already asked how they are doing, you are less likely to ask again.", true));
            rule.AddComponent(new KC_IDSelectionRequest("askDay", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "askDay.", true));
            rule.AddComponent(new KC_Utility(-5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);
            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you've already asked how they are doing, you are less likely to ask again.", true));
            rule.AddComponent(new KC_IDSelectionRequest("askDayReverse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "askDay.", true));
            rule.AddComponent(new KC_Utility(-5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you've have been asked how they have been doing, you should respond.", true));
            rule.AddComponent(new KC_IDSelectionRequest("neutralResponse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "askDay.", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);
            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you've have been asked how they have been doing, you should respond.", true));
            rule.AddComponent(new KC_IDSelectionRequest("goodResponse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "askDay.", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);
            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you've have been asked how they have been doing, you should respond.", true));
            rule.AddComponent(new KC_IDSelectionRequest("badResponse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "askDay.", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If your friend is doing well or okay, congradulate them.", true));
            rule.AddComponent(new KC_IDSelectionRequest("congratulate", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "response(good); response(neutral).", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If your friend is doing bad, console them.", true));
            rule.AddComponent(new KC_IDSelectionRequest("console", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "response(bad).", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you have already said how you are doing, don't say it again.", true));
            rule.AddComponent(new KC_IDSelectionRequest("goodResponse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "response(X).", true));
            rule.AddComponent(new KC_Utility(-5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);
            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you have already said how you are doing, don't say it again.", true));
            rule.AddComponent(new KC_IDSelectionRequest("badResponse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "response(X).", true));
            rule.AddComponent(new KC_Utility(-5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);
            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you have already said how you are doing, don't say it again.", true));
            rule.AddComponent(new KC_IDSelectionRequest("neutralResponse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "response(X).", true));
            rule.AddComponent(new KC_Utility(-5, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            rule = new Unit();
            rule.AddComponent(new KC_UnitID("If you have told someone how your day has been, ask them in return.", true));
            rule.AddComponent(new KC_IDSelectionRequest("askDayReverse", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "askDay, (congratulate; console).", true));
            rule.AddComponent(new KC_Utility(10, true));
            rule.AddComponent(new KC_ContentPool(DemoEnsembleLite.RulesPool, true));
            blackboard.AddUnit(rule);

            Unit dialogue = new Unit();

            dialogue.AddComponent(new KC_UnitID("greeting", true));
            dialogue.AddComponent(new KC_Text("Hello there", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "saidHello" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            dialogue = new Unit();
            dialogue.AddComponent(new KC_UnitID("askDay", true));
            dialogue.AddComponent(new KC_Text("How is your day going?", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "askDay" }, true));
            dialogue.AddComponent(new KC_PrologFactDeleteList(new string[] { "response(X)" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            dialogue = new Unit();
            dialogue.AddComponent(new KC_UnitID("askDayReverse", true));
            dialogue.AddComponent(new KC_Text("And you?", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "askDay" }, true));
            dialogue.AddComponent(new KC_PrologFactDeleteList(new string[] { "response(X)" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            dialogue = new Unit();
            dialogue.AddComponent(new KC_UnitID("neutralResponse", true));
            dialogue.AddComponent(new KC_Text("I'm okay.", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "response(neutral)" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            dialogue = new Unit();
            dialogue.AddComponent(new KC_UnitID("goodResponse", true));
            dialogue.AddComponent(new KC_Text("I'm great.", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "response(good)" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            dialogue = new Unit();
            dialogue.AddComponent(new KC_UnitID("badResponse", true));
            dialogue.AddComponent(new KC_Text("I've been tired.", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "response(bad)" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            dialogue = new Unit();
            dialogue.AddComponent(new KC_UnitID("console", true));
            dialogue.AddComponent(new KC_Text("That's too bad", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "console" }, true));
            dialogue.AddComponent(new KC_PrologFactDeleteList(new string[] { "askDay" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            dialogue = new Unit();
            dialogue.AddComponent(new KC_UnitID("congratulate", true));
            dialogue.AddComponent(new KC_Text("That's good, I'm glad.", true));
            dialogue.AddComponent(new KC_PrologFactAddList(new string[] { "congratulate" }, true));
            dialogue.AddComponent(new KC_PrologFactDeleteList(new string[] { "askDay" }, true));
            dialogue.AddComponent(new KC_ContentPool(DemoEnsembleLite.DialogPool, true));
            blackboard.AddUnit(dialogue);

            Unit        prologKBUnit = new Unit();
            KC_PrologKB prologKB     = new KC_PrologKB("Global", true);

            prologKBUnit.AddComponent(prologKB);

            /*
             * fixme: is there a better way to define a predicate for prolog than asserting and retracting it?
             */
            prologKB.Assert("saidHello.");
            prologKB.Retract("saidHello.");
            prologKB.Assert("askDay.");
            prologKB.Retract("askDay.");
            prologKB.Assert("response(neutral).");
            prologKB.Retract("response(neutral).");
            prologKB.Assert("console");
            prologKB.Retract("console");
            prologKB.Assert("congratulate");
            prologKB.Retract("congratulate");

            blackboard.AddUnit(prologKBUnit);
        }
        /*
         * Adds ContentUnits to blackboard for demo3, a simple context-free-grammar demo, no rule specificities,
         * no pushing or poping. Uses this grammar from the 12B assignment.
         * animal:cat,emu,okapi
         * emotion:happy,sad,elated,curious,sleepy
         * color:red,green,blue
         * name:emily,luis,otavio,anna,charlie
         * character:#name# the #adjective# #animal#
         * place:school,the beach,the zoo,Burning Man
         * adjective:#color#,#emotion#,
         * origin:once #character# and #character# went to #place#
         */
        public static Unit Demo3_2_DefineUnits(IBlackboard blackboard, string grammarPool)
        {
            // Start symbol
            Unit startSymbol = new Unit();

            startSymbol.AddComponent(new KC_IDSelectionRequest("Origin", true));
            startSymbol.AddComponent(new KC_TreeNode(null));
            startSymbol.AddComponent(new KC_ContentPool(grammarPool, true));
            startSymbol.AddComponent(new KC_Order(0, true));

            // OrderCounter
            Unit orderCounter = new Unit();

            orderCounter.AddComponent(new KC_OrderCounter(0));

            /*
             * Grammar rules
             */

            /* Origin rule
             * Origin --> Once #Character# and #Character# went to #Place#
             */
            Unit startRule = MakeRuleUnit("Origin", grammarPool, blackboard);

            // Define the RHS of Origin rule
            Unit[] startRHS = MakeUnitArray(6);
            startRHS[0].AddComponent(new KC_Text("Once", true));
            startRHS[1].AddComponent(new KC_IDSelectionRequest("Character", true));
            startRHS[2].AddComponent(new KC_Text("and", true));
            startRHS[3].AddComponent(new KC_IDSelectionRequest("Character", true));
            startRHS[4].AddComponent(new KC_Text("went to", true));
            startRHS[5].AddComponent(new KC_IDSelectionRequest("Place", true));
            startRule.AddComponent(new KC_Decomposition(startRHS, true));

            /*
             * Adjective rules
             * Adjective --> #Color#
             * Adjective --> #Emotion#
             */
            Unit adjectiveRule1 = MakeRuleUnit("Adjective", grammarPool, blackboard);

            // Define RHS of Adjective1 rule
            Unit[] adjectiveRule1RHS = MakeUnitArray(1);
            adjectiveRule1RHS[0].AddComponent(new KC_IDSelectionRequest("Color", true));
            adjectiveRule1.AddComponent(new KC_Decomposition(adjectiveRule1RHS, true));

            Unit adjectiveRule2 = MakeRuleUnit("Adjective", grammarPool, blackboard);

            // Define RHS of Adjective2 rule
            Unit[] adjectiveRule2RHS = MakeUnitArray(1);
            adjectiveRule2RHS[0].AddComponent(new KC_IDSelectionRequest("Emotion", true));
            adjectiveRule2.AddComponent(new KC_Decomposition(adjectiveRule2RHS, true));

            /*
             * Place rules
             * Place --> school
             * Place --> the beach
             * Place --> the zoo
             * Place --> Burning Man
             */
            string[] terminals1 = { "school", "the beach", "the zoo", "Burning Man" };
            MakeTerminalSingletons("Place", grammarPool, terminals1, blackboard);

            /*
             * Character rule
             * Character --> #name# the #adjective# #animal#
             */
            Unit characterRule = MakeRuleUnit("Character", grammarPool, blackboard);

            // Define RHS of Character rule
            Unit[] characterRuleRHS = MakeUnitArray(4);
            characterRuleRHS[0].AddComponent(new KC_IDSelectionRequest("Name", true));
            characterRuleRHS[1].AddComponent(new KC_Text("the", true));
            characterRuleRHS[2].AddComponent(new KC_IDSelectionRequest("Adjective", true));
            characterRuleRHS[3].AddComponent(new KC_IDSelectionRequest("Animal", true));
            characterRule.AddComponent(new KC_Decomposition(characterRuleRHS, true));

            /*
             * Name rules
             * Name --> emily
             * Name --> luis
             * Name --> otavio
             * Name --> anna
             * Name --> charlie
             */
            string[] terminals2 = { "emily", "luis", "otavio", "anna", "charlie" };
            MakeTerminalSingletons("Name", grammarPool, terminals2, blackboard);

            /*
             * Color rules
             * Color --> red
             * Color --> green
             * Color --> blue
             */
            string[] terminals3 = { "red", "green", "blue" };
            MakeTerminalSingletons("Color", grammarPool, terminals3, blackboard);

            /*
             * Emotion rules
             * Emotion --> happy
             * Emotion --> sad
             * Emotion --> curious
             * Emotion --> sleepy
             */
            string[] terminals4 = { "happy", "sad", "curious", "sleepy" };
            MakeTerminalSingletons("Emotion", grammarPool, terminals4, blackboard);

            /*
             * Animal rules
             * Animal --> cat
             * Animal --> emu
             * Animal --> okapi
             */
            string[] terminals5 = { "cat", "emu", "okapi" };
            MakeTerminalSingletons("Animal", grammarPool, terminals5, blackboard);

            blackboard.AddUnit(startSymbol);
            blackboard.AddUnit(orderCounter);
            return(startSymbol);
        }
        /*
         * Adds ContentUnits to blackboard for demo3, a simple context-free-grammar demo, no rule specificities,
         * no pushing or poping.
         */

        public static Unit Demo3_1_DefineUnits(IBlackboard blackboard, string grammarPool)
        {
            // Start symbol
            Unit startSymbol = new Unit();

            startSymbol.AddComponent(new KC_IDSelectionRequest("Start", true));
            startSymbol.AddComponent(new KC_TreeNode(null));
            startSymbol.AddComponent(new KC_ContentPool(grammarPool, true));
            startSymbol.AddComponent(new KC_Order(0, true));

            // OrderCounter
            Unit orderCounter = new Unit();

            orderCounter.AddComponent(new KC_OrderCounter(0));

            /*
             * Grammar rules
             */

            // Start rule
            Unit startRule = new Unit();

            startRule.AddComponent(new KC_UnitID("Start", true));
            startRule.AddComponent(new KC_ContentPool(grammarPool, true));

            // Define the RHS of start rule
            Unit[] startRHS = { new Unit(), new Unit() };
            startRHS[0].AddComponent(new KC_Text("Hello", true));
            startRHS[1].AddComponent(new KC_IDSelectionRequest("Place", true));

            startRule.AddComponent(new KC_Decomposition(startRHS, true));

            // Place rule
            Unit placeRule1 = new Unit();

            placeRule1.AddComponent(new KC_UnitID("Place", true));
            placeRule1.AddComponent(new KC_ContentPool(grammarPool, true));

            // Define RHS for placeRule1
            Unit[] placeRule1RHS = { new Unit() };
            placeRule1RHS[0].AddComponent(new KC_Text("world", true));

            placeRule1.AddComponent(new KC_Decomposition(placeRule1RHS, true));

            Unit placeRule2 = new Unit();

            placeRule2.AddComponent(new KC_UnitID("Place", true));
            placeRule2.AddComponent(new KC_ContentPool(grammarPool, true));

            // Define RHS for placeRule2
            Unit[] placeRule2RHS = { new Unit() };
            placeRule2RHS[0].AddComponent(new KC_Text("universe", true));

            placeRule2.AddComponent(new KC_Decomposition(placeRule2RHS, true));

            blackboard.AddUnit(startSymbol);
            blackboard.AddUnit(orderCounter);
            blackboard.AddUnit(startRule);
            blackboard.AddUnit(placeRule1);
            blackboard.AddUnit(placeRule2);

            return(startSymbol);
        }
        public static void Demo1_Slots_DefineCUs(IBlackboard blackboard)
        {
            ContentUnit start = new ContentUnit();

            start.Metadata[ContentUnitID] = "start";
            start.Content[Text]           = "You stand before an old wooden door.";

            ContentUnit start_Choice1 = new ContentUnit();

            start_Choice1.Metadata[TargetContentUnitID] = "open door";
            start_Choice1.Content[Text] = "Open the door";

            ContentUnit start_Choice2 = new ContentUnit();

            start_Choice2.Metadata[TargetContentUnitID] = "wait";
            start_Choice2.Content[Text] = "Wait";

            ContentUnit openDoor = new ContentUnit();

            openDoor.Metadata[ContentUnitID] = "open door";
            openDoor.Content[Text]           = "Opening the door, you step forth into adventure.";

            ContentUnit waited = new ContentUnit();

            waited.Metadata[ContentUnitID] = "wait";
            waited.Content[Text]           = "You wait fruitlessly in front the door.";

            ContentUnit waitedChoice1 = new ContentUnit();

            waitedChoice1.Metadata[TargetContentUnitID] = "waited again";
            waitedChoice1.Content[Text] = "Wait again";

            ContentUnit waitedChoice2 = new ContentUnit();

            waitedChoice2.Metadata[TargetContentUnitID] = "open door after waiting";
            waitedChoice2.Content[Text] = "Finally open the door";

            ContentUnit waitedAgain = new ContentUnit();

            waitedAgain.Metadata[ContentUnitID] = "waited again";
            waitedAgain.Content[Text]           = "Sunk in a deep malaise, you wait the rest of your life.";

            ContentUnit openDoorAfterWaiting = new ContentUnit();

            openDoorAfterWaiting.Metadata[ContentUnitID] = "open door after waiting";
            openDoorAfterWaiting.Content[Text]           = "Breaking through your reservations, you step forward into a life of adventure.";

            blackboard.AddUnit(start);
            blackboard.AddUnit(start_Choice1);
            blackboard.AddUnit(start_Choice2);
            blackboard.AddUnit(openDoor);
            blackboard.AddUnit(waited);
            blackboard.AddUnit(waitedChoice1);
            blackboard.AddUnit(waitedChoice2);
            blackboard.AddUnit(waitedAgain);
            blackboard.AddUnit(openDoorAfterWaiting);

            blackboard.AddLink(start, start_Choice1, LinkTypes.L_Choice);
            blackboard.AddLink(start, start_Choice2, LinkTypes.L_Choice);
            blackboard.AddLink(waited, waitedChoice1, LinkTypes.L_Choice);
            blackboard.AddLink(waited, waitedChoice2, LinkTypes.L_Choice);
        }
        /*
         * Adds ContentUnits to blackboard for demo2, a choice-based demo with prolog applicability tests for choice setups.
         */
        public static void Demo2_DefineUnits(IBlackboard blackboard)
        {
            Unit start = new Unit();

            start.AddComponent(new KC_UnitID("start", true));
            start.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "true.", true));
            start.AddComponent(new KC_Text("An old gentleman stands before you.", true));

            Unit choice_AskForHelp = new Unit();

            choice_AskForHelp.AddComponent(new KC_IDSelectionRequest("ask for help", true));
            choice_AskForHelp.AddComponent(new KC_Text("Ask for help", true));

            Unit choice_introduceYourself = new Unit();

            choice_introduceYourself.AddComponent(new KC_IDSelectionRequest("introduce yourself", true));
            choice_introduceYourself.AddComponent(new KC_PrologFactAddList(new string[] { "introducedYourself" }, true));
            choice_introduceYourself.AddComponent(new KC_Text("Introduce yourself", true));

            Unit askForHelp1 = new Unit();

            askForHelp1.AddComponent(new KC_UnitID("ask for help", true));
            askForHelp1.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "introducedYourself.", true));
            askForHelp1.AddComponent(new KC_Text("'Since you introduced yourself so nicely, I'm happy to help!'", true));

            Unit askForHelp2 = new Unit();

            askForHelp2.AddComponent(new KC_UnitID("ask for help", true));
            askForHelp2.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "\\+ introducedYourself.", true));
            askForHelp2.AddComponent(new KC_Text("Eyeing you suspiciously the old man replies 'Who are you?'", true));

            Unit introduceYourself = new Unit();

            introduceYourself.AddComponent(new KC_UnitID("introduce yourself", true));
            introduceYourself.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "true.", true));
            introduceYourself.AddComponent(new KC_Text("'Very nice to meet you!'", true));

            blackboard.AddUnit(start);
            blackboard.AddUnit(choice_AskForHelp);
            blackboard.AddUnit(choice_introduceYourself);
            blackboard.AddUnit(askForHelp1);
            blackboard.AddUnit(askForHelp2);
            blackboard.AddUnit(introduceYourself);

            blackboard.AddLink(start, choice_AskForHelp, LinkTypes.L_Choice);
            blackboard.AddLink(start, choice_introduceYourself, LinkTypes.L_Choice);
            blackboard.AddLink(askForHelp2, choice_AskForHelp, LinkTypes.L_Choice);
            blackboard.AddLink(askForHelp2, choice_introduceYourself, LinkTypes.L_Choice);
            blackboard.AddLink(introduceYourself, choice_AskForHelp, LinkTypes.L_Choice);

            Unit        prologKBUnit = new Unit();
            KC_PrologKB prologKB     = new KC_PrologKB("Global", true);

            prologKBUnit.AddComponent(prologKB);

            /*
             * fixme: is there a better way to define a predicate for prolog than asserting and retracting it?
             */
            prologKB.Assert("introducedYourself.");
            prologKB.Retract("introducedYourself.");

            blackboard.AddUnit(prologKBUnit);
        }
        public static void TavernTalk_DefineUnits(IBlackboard blackboard)
        {
            //Abstract Social Moves:
            Unit move = new Unit();

            move.AddComponent(new KC_UnitID("tell", true));
            move.AddComponent(new KC_ContentPool(AbstractSocialMoves));
            blackboard.AddUnit(move);

            move = new Unit();
            move.AddComponent(new KC_UnitID("ask", true));
            move.AddComponent(new KC_ContentPool(AbstractSocialMoves));
            blackboard.AddUnit(move);



            //Character Knowledge Base Facts:

            /*
             * Structure should contain at least:
             *      id: string
             *      subject: string
             *      verb: string
             *      object: string
             *      opinion: int
             *
             * Will likely also want things like:
             *      time
             *      location
             *      state (as opposed to verb)
             *
             */

            Unit fact = new Unit();

            fact.AddComponent(new KC_UnitID("Alicia dating Jasper", true));
            move.AddComponent(new KC_ContentPool(CharacterKnowledgeBase));
            blackboard.AddUnit(fact);

            fact = new Unit();
            fact.AddComponent(new KC_UnitID("Alicia is busy", true));
            move.AddComponent(new KC_ContentPool(CharacterKnowledgeBase));
            blackboard.AddUnit(fact);



            //Characters list:
            // I think this should just be the characters currently in the bar
            // may each eventaully have their own knowledge pool?
            // where is social relations stored? In Prologue?
            Unit character = new Unit();

            character.AddComponent(new KC_UnitID("Barkeep", true));
            move.AddComponent(new KC_ContentPool(Characters));
            blackboard.AddUnit(character);

            character = new Unit();
            character.AddComponent(new KC_UnitID("Marco", true));
            move.AddComponent(new KC_ContentPool(Characters));
            blackboard.AddUnit(character);



            //Social Rules:
            Unit rule = new Unit();

            rule.AddComponent(new KC_UnitID("Ask friends stuff", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.ApplTest_Prolog, "ask(X).", true));
            rule.AddComponent(new KC_PrologExpression(KCNames.SalienceTest_Prolog, "friends(X).", true));
            rule.AddComponent(new KC_Utility(5, true));
            rule.AddComponent(new KC_ContentPool(SocialRules, true));
            blackboard.AddUnit(rule);



            //Prolog Database:

            Unit        prologKBUnit = new Unit();
            KC_PrologKB prologKB     = new KC_PrologKB("Global", true);

            prologKBUnit.AddComponent(prologKB);

            /*
             * fixme: is there a better way to define a predicate for prolog than asserting and retracting it?
             */
            prologKB.Assert("ask(a).");
            prologKB.Retract("ask(a).");
            prologKB.Assert("friends(Marco).");
            prologKB.Retract("friends(Marco).");

            blackboard.AddUnit(prologKBUnit);
        }