public NounHolder GenerateAllStems(bool debugPrint)
        {
            NounHolder holder = new NounHolder();

            holder.englishNounKey = new Dictionary <string, Noun>();
            Debug.WriteLine("D: Nouns:");
            foreach (var englishNoun in holder.englishNouns)
            {
                var k = GenerateRoot(englishNoun);
                holder.englishNounKey.Add(englishNoun, k);
                //TODO:Remove in final
                Debug.WriteLine($">>>{englishNoun}  :  {k}");
            }
            return(holder);
        }
        public void Start(string[] args)
        {
            Instance           = this;
            _nounEndingHandler = new NounEndingHandler();
            _stemGenerator     = new StemGenerator();
            _nounHolder        = _stemGenerator.GenerateAllStems(true);
            _verbHolder        = new VerbHolder(_stemGenerator);
            _adjectiveHolder   = new AdjectiveHolder(_stemGenerator);
            NounPrefabs.Init(_nounHolder, _verbHolder, _adjectiveHolder, _nounEndingHandler);
            _gameState = new GameState();

            CmdRegistration.RegisterCommands();

            if (args.Length != 0)
            {
                return;
            }
            MainGameLoop();
        }
        public static void Init(NounHolder nounHolder, VerbHolder verbHolder, AdjectiveHolder adjectiveHolder,
                                NounEndingHandler handler)
        {
            prefabs = new Dictionary <string, NounObject>();

            GrantPuzzlePrefabs();



            Dictionary <string, Func <NounObject, string> > tmp = new Dictionary <string, Func <NounObject, string> >();

            //{
            //    {
            //        "sight",
            //        (x) => $"The table is {x.properties["color"]}.  On the table there is:\n{x.FormattedChildren()}"
            //    }
            //};
            prefabs.Add("table", new NounObject(nounHolder.englishNounKey["Table"], "A table.", tmp, false, true));
            prefabs["table"].properties.Add("color", "white");

            //tmp = new Dictionary<string, Func<NounObject, string>>
            //{
            //    {"sight", (x) => $"The apple is {x.properties["color"]}."}
            //};
            prefabs.Add("apple", new NounObject(nounHolder.englishNounKey["Apple"], "An apple.", tmp));
            prefabs["apple"].properties.Add("color", "red");

            prefabs.Add("lever",
                        new NounObject(new Noun(null, "lever"), "A wooden vertical lever.",
                                       new Dictionary <string, Func <NounObject, string> >()
            {
                { "sight", (x) => "There is a plus above the lever and a minus below the lever." }
            }, false)
                        .AddProperty("switchStatus", "up")
                        .SetUseAction((x, isInInventory) =>
            {
                if (isInInventory)
                {
                    return("How did a lever get in your inventory lol");
                }
                if (!x.properties.ContainsKey("switchStatus"))
                {
                    Debug.WriteLine("Lever did not have switchStatus property");
                }
                if (x.properties["switchStatus"] == "up")
                {
                    x.properties["switchStatus"] = "down";
                    return("You flip the switch into the down position.");
                }
                else
                {
                    x.properties["switchStatus"] = "up";
                    return("You flip the switch into the up position.");
                }
            })
                        );

            #region Wands



            prefabs.Add("OrangeColorChangingWand",
                        new Wand(new Noun(null, "OrangeColorChangingWand"), "An orange wand").AddProperty("inscription",
                                                                                                          $"{nounHolder.englishNounKey["Apple"].Accusative(handler)} {adjectiveHolder.adjectives["orange"].word} {verbHolder.verbs["Change color"].verb}")
                        .AddProperty("color", "orange"));
            prefabs.Add("BlueColorChangingWand",
                        new Wand(new Noun(null, "BlueColorChangingWand"), "A blue wand").AddProperty("inscription",
                                                                                                     $"{nounHolder.englishNounKey["Apple"].Accusative(handler)} {adjectiveHolder.adjectives["blue"].word} {verbHolder.verbs["Change color"].verb}")
                        .AddProperty("color", "blue"));
            prefabs.Add("BlankWand",
                        new Wand(new Noun(null, "BlankWand"), "A plain white wand").AddProperty("color", "white"));

            #endregion


            prefabs.Add("blankPaper", new NounObject(new Noun(nounHolder.englishNounKey["Paper"].stem, "Paper"), "A piece of paper.", (x) => "A piece of paper.")
                        .AddProperty("color", "white")
                        .AddProperty("canBeWritten", true.ToString())
                        .SetUseAction
                            ((x, isInInv) => {
                if (!isInInv)
                {
                    return("The paper has to be in your inventory!");
                }
                if (Program.Instance._gameState.isEmpowered == false)
                {
                    return("You look at the paper.  Seems pretty ordinary.  Not very interesting though...");
                }
                if (x.properties.ContainsKey("writing"))
                {
                    Console.WriteLine(TextUtils.Pick("You let magic flow from your fingertips to the paper."));
                    var k = Program.Instance.SpellCast.CastSpell(x.properties["writing"]);
                    Program.Instance.RemoveObject(x);
                    Console.WriteLine(k);
                    return("The paper disappears!");
                }
                return("Yup.  That's a sheet of paper.  Seems like you could write on it or something.");
            }
                            ));
            prefabs.Add("pen", new NounObject(new Noun(null, "Pen"), "A pen", (x) => "A pen, used for writing.").AddProperty("color", "black").AddProperty("writing", null).SetUseAction(
                            (x, isInInv) =>
            {
                if (!isInInv)
                {
                    return("The pen has to be in your inventory to write with it!");
                }
                Console.WriteLine("What object will you write on?");
                Console.Write(">>");
                var objToWriteOn = Program.Instance.FindObject(Console.ReadLine(), true);
                if (objToWriteOn != null && objToWriteOn.Value.Value == null)
                {
                    return("I can't find that!");
                }
                if (objToWriteOn == null)
                {
                    return("I can't find that");
                }
                if (objToWriteOn.Value.Value.properties.ContainsKey("canBeWritten") &&
                    objToWriteOn.Value.Value.properties["canBeWritten"] == true.ToString())
                {
                    Console.WriteLine("What will you write down?");
                    Console.Write(">>");
                    var writing = Console.ReadLine();
                    objToWriteOn.Value.Value.properties["writing"] = writing;
                    return($"You write \"{writing}\" on the {objToWriteOn.Value.Key.ToLower()}");
                }
                return("You can't write on that!");
            }));
            #region Books

            prefabs.Add("empowermentBook",
                        new Book(new Noun(null, "Old Journal"), "A book containing arcane secrets.", new List <string>()
            {
                "The language of magic is very simple.  Nouns have four cases.  The first case is the nominative case.  This is used for the subject of the sentence.  In simple spells the nominative case doesn't come up much.",
                "Another case is the accusative case.  This is the object that has the action acted upon.",
                "Finally there is the topic of posession.  If the object is merely sitting in the room, then I can use the spell as usual.  But if the object is sitting on a table, in a chest, or even on my person, then I must qualify the spell with a noun in the genitive case, followed by the noun in the accusative case.",
                $"Verbs do not conjugate depending on the subject, instead the subject is determined by the case of the noun.  I have learned the word \"{Program.Instance._verbHolder.verbs["Change color"].verb}\".  This word allows me to change the color of a noun in the accusative.  The spells are comprised of the accusative noun that I want to change the color of, \"{Program.Instance._verbHolder.verbs["Change color"].verb}\", and the color in the magical language in any order.",
                "There are many different ways to activate spells, most involve inscribing the spell onto a magical object.",
                "[The rest of the pages are burnt.]"
            })
            {
                senses =
                    new Dictionary <string, Func <NounObject, string> >()
                {
                    { "sight", (x) => $"The book is a short journal." }
                },
                onReadAction = (x) =>
                {
                    if
                    (
                        Program.Instance._gameState.isEmpowered == false)
                    {
                        Console
                        .WriteLine
                            ("You feel energy rushing through you!  You can now use magical items!");
                        Program
                        .Instance
                        ._gameState
                        .isEmpowered
                            =
                                true;
                    }
                }
            });



            #endregion Books


            prefabs.Add("debug3_pedestal",
                        new NounObject(new Noun(null, "PinkPedestal"), "A pink pedestal",
                                       new Dictionary <string, Func <NounObject, string> >()
            {
                {
                    "sight",
                    (x) =>
                    $"Written at the bottom of the pedestal, you see the words \"Pink equals {Program.Instance._adjectiveHolder.adjectives["pink"].word}\""
                }
            }, false, true).AddProperty("color", "pink").SetOnUpdate(
                            (x) =>
            {
                if (x.nounChildren.Count != 0)
                {
                    foreach (var nounObject in x.nounChildren)
                    {
                        if (nounObject.Value.myNoun.stem == prefabs["apple"].myNoun.stem)
                        {
                            if (nounObject.Value.properties["color"] == "pink")
                            {
                                if (Program.Instance._gameState.currentRoom().roomKey == "Debug3")
                                {
                                    if (
                                        !Program.Instance._gameState.currentRoom()
                                        .adjoiningRooms.ContainsKey(RoomDirections.SOUTH))
                                    {
                                        Console.WriteLine("The exit door opens!");
                                        Program.Instance._gameState.roomHolder["Debug3"].adjoiningRooms.Add(
                                            RoomDirections.SOUTH, () => "Debug4");
                                    }
                                }
                            }
                        }
                    }
                }
            }));



            tmp = new Dictionary <string, Func <NounObject, string> >()
            {
                //TODO: Make more adventure-y
                { "sight", (x) => $"A machine used for inscription." }
            };
            prefabs.Add("inscriptionMachine",
                        new NounObject(new Noun(null, "inscriptionMachine"),
                                       "A machine used to inscribe new inscriptions to a wand.", tmp, false, false)
            {
                UseAction = (x, isInInv) =>
                {
                    if (isInInv)
                    {
                        Debug.WriteLine("Wow the inscription table is in the inventory, how'd that happen lol.");
                    }
                    Console.WriteLine("What wand will you inscribe?");
                    Console.Write(">>");
                    bool wandIsInInv;
                    var obj = Program.Instance.FindObject(Console.ReadLine(), out wandIsInInv, true);
                    if (obj == null)
                    {
                        return("I can't find that wand!");
                    }
                    if (!(obj.Value.Value is Wand))
                    {
                        return("You can only inscribe wands!");
                    }
                    if (wandIsInInv)
                    {
                        Console.WriteLine("What should the new inscription say?");
                        Console.Write(">>");
                        var inscription = Console.ReadLine();
                        obj.Value.Value.properties["inscription"] = inscription;
                        return($"You inscribe \"{inscription}\" onto the wand.");
                    }
                    else
                    {
                        return("The wand has to be in your inventory!");
                    }
                }
            })
            ;
            //   prefabs.Add();
        }
        private string ParseLine(string readLine)
        {
            if (CmdRegistration.basicCommandMap.ContainsKey(readLine.ToLower()))
            {
                return(CmdRegistration.basicCommandMap[readLine.ToLower()]());
            }
            if (CmdRegistration.complexCommandMap.Any(func => readLine.ToLower().Split(' ')[0] == func.Key) && readLine.ToLower().Split(' ').Length > 1)
            {
                return(CmdRegistration.complexCommandMap[readLine.ToLower().Split(' ')[0]](readLine.ToLower().Substring(readLine.ToLower().Split(' ')[0].Length + 1)));
            }


            #region debugging commands

            //Debug data
            if (readLine.ToLower().StartsWith("d:"))
            {
                switch (readLine.ToLower())
                {
                case "d:connectroom":
                    Console.WriteLine("What room should I connect to this one?");
                    Console.Write(">>");
                    string whatRoomShouldIConnectToThisOne = Console.ReadLine();
                    Console.WriteLine("What direction should I connect it with?");
                    Console.Write(">>");
                    bool           isWork = false;
                    RoomDirections direc;
                    isWork = Enum.TryParse(Console.ReadLine().ToUpper(), false, out direc);
                    if (isWork)
                    {
                        return("Connected rooms");
                    }
                    while (!isWork)
                    {
                        Console.WriteLine("I'm sorry, I didn't understand that, please enter \"north\" \"south\" \"east\" or \"west\".");
                        isWork = Enum.TryParse(Console.ReadLine(), false, out direc);
                    }
                    if (_gameState.currentRoom().adjoiningRooms.ContainsKey(direc))
                    {
                        return("Already have a room connected in that direction!");
                    }
                    _gameState.currentRoom().adjoiningRooms.Add(direc, () => whatRoomShouldIConnectToThisOne);
                    return("Connected rooms");

                case "d:empower":
                    _gameState.isEmpowered = true;
                    return("You are empowered now.");

                case "d:cast":
                    Console.Write(">>");
                    return(SpellCast.CastSpell(Console.ReadLine()).ToString());


                case "d:addnoun":
                    Console.WriteLine("What should I call this noun?");
                    Console.Write(">>");
                    string nounName = Console.ReadLine();
                    Console.WriteLine("What is the prefab of this noun called?");
                    Console.Write(">>");
                    string nounObjPossible = Console.ReadLine();
                    if (String.IsNullOrEmpty(nounObjPossible) || string.IsNullOrEmpty(nounName) | !NounPrefabs.prefabs.ContainsKey(nounObjPossible.ToLower()))
                    {
                        return("Not a valid noun.");
                    }
                    _gameState.currentRoom().Children.Add(nounName, NounPrefabs.prefabs[nounObjPossible.ToLower()]);
                    return("added");

                case "d:isnoun":
                    Console.Write(">>");
                    return(_nounHolder.GetIsNoun(Console.ReadLine(), _nounEndingHandler).ToString());

                case "d:generateallnouns":
                    _nounHolder = _stemGenerator.GenerateAllStems(true);
                    return("");

                case "d:parsenoun":
                    Console.Write(">>");
                    var parseInput = Console.ReadLine();
                    var returnedNounInformation = _nounHolder.GetNounFromInput(parseInput, _nounEndingHandler);
                    if (!_nounHolder.GetIsNoun(parseInput, _nounEndingHandler))
                    {
                        return("That's not a Noun!");
                    }
                    if (_nounHolder.EnglishDefinitionFromNoun(returnedNounInformation.Value.Word) == null)
                    {
                        return
                            ($"Stem : {returnedNounInformation.Value.Stem}\nCase : {returnedNounInformation.Value.NounCase}\nEnglish Definition : No definition found");
                    }
                    return
                        ($"Stem : {returnedNounInformation.Value.Stem}\nCase : {returnedNounInformation.Value.NounCase}\nEnglish Definition : {_nounHolder.EnglishDefinitionFromNoun(returnedNounInformation.Value.Word)}");

                case "d:regenerateendings":
                    _nounEndingHandler = new NounEndingHandler();
                    return("Regeneration Completed!");

                case "d:listendings":
                    return
                        ($"Nominative : {_nounEndingHandler.nominativeEnding}\nGenitive : {_nounEndingHandler.genitiveEnding}\nDative : {_nounEndingHandler.dativeEnding}\nAccusative : {_nounEndingHandler.accusativeEnding}");

                default:
                    return
                        ("No matching command\n Try:\nd:declineroot\nd:regenerateendings\nd:findtypeandstemfromword\nd:generatestem\nd:generateword");
                }
            }
            #endregion debugging commands

            return(TextUtils.Pick("Sorry, I missed that.", "I didn't understand that.", "That doesn't make sense!", "Huh?"));
        }