public static T ChooseWord <T>(this WordDictionary dict, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen, Func <T, bool> wordPredicate) where T : Word
        {
            _ = dict ?? throw new ArgumentNullException(nameof(dict));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));
            _ = wordPredicate ?? throw new ArgumentNullException(nameof(wordPredicate));

            var       count = dict.CountOf <T>();
            T         result;
            int       attempts    = 0;
            const int maxAttempts = 5;

            do
            {
                var idx = randomness.Next(count);
                result = dict.GetWordAtIndex <T>(idx);

                attempts++;
                if (attempts >= maxAttempts)
                {
                    // This way is much slower when lots of words match the predicate, but faster if few do.
                    return(ChooseWordAlternate <T>(dict, randomness, alreadyChosen, wordPredicate));
                }
            } while (alreadyChosen.Contains(result) || !wordPredicate(result));

            return(result);
        }
示例#2
0
        public override void AddWordTemplate(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
        {
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
            _ = currentTemplate ?? throw new ArgumentNullException(nameof(currentTemplate));

            // Conjunctions are very simple: they either join noun clauses or entire phrases (which will require another verb clause).
            // I'm not allowing a conjunction to be either though.

            if (JoiningNounFactor > 0 && JoiningPhraseFactor > 0)
            {
                throw new Exception("Conjunctions may join noun clauses or entire phrases, but not both. Set one of JoinsNoun and JoinsPhrase to 0.");
            }
            if (JoiningNounFactor <= 0 && JoiningPhraseFactor <= 0)
            {
                throw new Exception("Conjunctions may join noun clauses or entire phrases. Set one of JoinsNoun and JoinsPhrase to greater than 0.");
            }

            // Common or proper noun?
            if (JoiningNounFactor > 0)
            {
                currentTemplate.Add(new NounConjunctionTemplate());
            }
            if (JoiningPhraseFactor > 0)
            {
                currentTemplate.Add(new PhraseConjunctionTemplate());
            }
        }
        public override void AddWordTemplate(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
        {
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
            _ = currentTemplate ?? throw new ArgumentNullException(nameof(currentTemplate));

            if (CommonNounFactor + ProperNounFactor + NounFromAdjectiveFactor <= 0)
            {
                // No noun clause at all!
                return;
            }

            // How do we form the noun?
            // - Common noun.
            // - Proper noun.
            // - Adjective with indefinite pronoun?
            if (randomness.WeightedCoinFlip(CommonNounFactor, ProperNounFactor + NounFromAdjectiveFactor))
            {
                this.AddCommonNoun(randomness, dictionary, currentTemplate);
            }
            else if (randomness.WeightedCoinFlip(ProperNounFactor, NounFromAdjectiveFactor))
            {
                this.AddProperNoun(randomness, dictionary, currentTemplate);
            }
            else if (NounFromAdjectiveFactor != 0)
            {
                this.AddAdjectiveAsNoun(randomness, dictionary, currentTemplate);
            }
            else
            {
                throw new Exception("Unexpected state.");
            }
        }
        public override void AddWordTemplate(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
        {
            _ = currentTemplate ?? throw new ArgumentNullException(nameof(currentTemplate));

            // Simply select an AnyTemplate.
            // No fancy logic here at all.
            currentTemplate.Add(new AnyTemplate());
        }
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            var word = words.ChooseWord <Interrogative>(randomness, alreadyChosen);

            return(new WordAndString(word, SubjectIsPlural ? word.Plural : word.Singular));
        }
示例#6
0
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            var word = words.ChooseWord <Verb>(randomness, alreadyChosen, w => w.HasForm(this.Tense, this.SubjectIsPlural) && w.IsTransitive == this.SelectTransitive);

            return(new WordAndString(word, word.GetForm(this.Tense, this.SubjectIsPlural)));
        }
示例#7
0
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            var word = words.ChooseWord <Conjunction>(randomness, alreadyChosen, w => w.SeparatesNouns);

            return(new WordAndString(word, word.Value));
        }
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            var word = words.ChooseWord <SpeechVerb>(randomness, alreadyChosen);

            return(new WordAndString(word, word.Past));
        }
        private static T ChooseWordAlternate <T>(this WordDictionary dict, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen, Func <T, bool> wordPredicate) where T : Word
        {
            var possibleWords     = dict.OfType <T>().Where(w => wordPredicate(w) && !alreadyChosen.Contains(w)).ToList();
            var matchingWordCount = possibleWords.Count;

            if (matchingWordCount == 0)
            {
                throw new Exception(String.Format("Unable to choose a {0} at random. There are no words which match the specified predicate which are not already chosen.", typeof(T).Name));
            }
            var idx    = randomness.Next(matchingWordCount);
            var result = possibleWords[idx];

            return(result);
        }
        public override void SecondPassOfWordTemplate(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
        {
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
            _ = currentTemplate ?? throw new ArgumentNullException(nameof(currentTemplate));

            // If we deal with intransitive by having no object, remove the object!
            if (this._LastVerbTemplateIndex >= 0)
            {
                while (currentTemplate.Count > this._LastVerbTemplateIndex + 1)
                {
                    currentTemplate.RemoveAt(this._LastVerbTemplateIndex + 1);
                }
            }
        }
示例#11
0
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            // This won't always produce the correct result.
            if (this.IsDefinite)
            {
                return(new WordAndString(words.TheArticle, words.TheArticle.Definite));
            }
            else
            {
                return(new WordAndString(words.TheArticle, words.TheArticle.Indefinite));
            }
        }
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            if (this._NounIsSingular)
            {
                var w = (Number)words.First(x => x is Number n && n.RequiresSingularNoun);
                return(new WordAndString(w, w.Value));
            }
            else
            {
                var word = words.ChooseWord <Number>(randomness, alreadyChosen, w => !w.RequiresSingularNoun);
                return(new WordAndString(word, word.Value));
            }
        }
示例#13
0
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            var word = words.ChooseWord <PersonalPronoun>(randomness, alreadyChosen);

            if (!this._IsPlural)
            {
                return(new WordAndString(word, word.Singular));
            }
            else
            {
                return(new WordAndString(word, word.Plural));
            }
        }
        public override void AddWordTemplate(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
        {
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
            _ = currentTemplate ?? throw new ArgumentNullException(nameof(currentTemplate));

            // Direct speech verbs are very simple cases of verbs. They rely on a preceeding noun clause to make sense.
            var chosenDirectSpeech = (DirectSpeechFactor + NoDirectSpeechFactor > 0) && // Case where neither is specified: assume no direct speech.
                                     randomness.WeightedCoinFlip(DirectSpeechFactor, NoDirectSpeechFactor);

            if (chosenDirectSpeech)
            {
                currentTemplate.Add(new SpeechVerbTemplate());
            }
            else
            {
                // No direct speech: remove any preceeding noun templates.
                var nounClauseTemplates = new HashSet <Type>()
                {
                    typeof(NounTemplate),
                    typeof(AdjectiveTemplate),
                    typeof(ProperNounTemplate),
                    typeof(ArticleTemplate),
                    typeof(DemonstrativeTemplate),
                    typeof(PersonalPronounTemplate),
                    typeof(PrepositionTemplate)
                };
                var toRemove = currentTemplate.Reverse().TakeWhile(wt => nounClauseTemplates.Contains(wt.GetType())).ToList();
                if (toRemove.Count == currentTemplate.Count)
                {
                    currentTemplate.Clear();
                }
                else
                {
                    foreach (var x in toRemove)
                    {
                        currentTemplate.Remove(x);
                    }
                }
            }
        }
示例#15
0
        public override WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen)
        {
            _ = words ?? throw new ArgumentNullException(nameof(words));
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = alreadyChosen ?? throw new ArgumentNullException(nameof(alreadyChosen));

            // Select a word.
            Word word;

            do
            {
                var idx = randomness.Next(words.Count);
                word = words[idx];
            } while (word == null || alreadyChosen.Contains(word));

            // Select a form.
            var forms = word.AllForms().ToList();
            var form  = forms[randomness.Next(forms.Count)];

            return(new WordAndString(word, form));
        }
        private void AddCommonNoun(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
        {
            // Common nouns allow for the full range of extra stuff.
            bool isPlural;

            AddNounPrelude(randomness, dictionary, currentTemplate, out isPlural);

            // Add a number? Only for plurals, if they are choosable.
            if (NumberFactor + NoNumberFactor > 0 && (isPlural || PluralityFactor == 0))
            {
                if (!isPlural &&
                    !(currentTemplate.Any() && currentTemplate.Last() is ArticleTemplate at && !at.IsDefinite) &&
                    randomness.WeightedCoinFlip(NumberFactor, NoNumberFactor))
                {
                    // Singulars cannot have an indifinite article.
                    currentTemplate.Add(new NumberTemplate(!isPlural));
                }
                else if (isPlural && randomness.WeightedCoinFlip(NumberFactor, NoNumberFactor))
                {
                    currentTemplate.Add(new NumberTemplate(!isPlural));
                }
            }
 public abstract WordAndString ChooseWord(WordDictionary words, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen);
 public override void SecondPassOfWordTemplate(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
 {
     // No-op.
 }
        public override void AddWordTemplate(Random.RandomSourceBase randomness, WordDictionary dictionary, IList <WordTemplate.Template> currentTemplate)
        {
            _ = randomness ?? throw new ArgumentNullException(nameof(randomness));
            _ = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
            _ = currentTemplate ?? throw new ArgumentNullException(nameof(currentTemplate));

            this._LastVerbTemplateIndex = -1;

            // Figuring out if the verb will be plural or not is... well... complicated.
            bool subjectIsPlural;
            int  speechVerbIdx = -1, indefiniteNounIdx = -1;
            bool containsDirectSpeech   = currentTemplate.OfType <SpeechVerbTemplate>().Any();
            bool containsIndefiniteNoun = currentTemplate.OfType <IndefinitePronounTemplate>().Any();

            if (containsDirectSpeech)
            {
                speechVerbIdx = CollectionHelper.IndexOfType(currentTemplate, typeof(SpeechVerbTemplate));
            }
            if (containsIndefiniteNoun)
            {
                indefiniteNounIdx = CollectionHelper.IndexOfType(currentTemplate, typeof(IndefinitePronounTemplate));
            }

            var ntemp = !containsDirectSpeech?currentTemplate.OfType <NounTemplate>().FirstOrDefault()
                            : currentTemplate.Skip(speechVerbIdx).OfType <NounTemplate>().FirstOrDefault();

            var ptemp = containsIndefiniteNoun ? (currentTemplate[indefiniteNounIdx] as IndefinitePronounTemplate) : null;

            if (ptemp == null && ntemp == null)
            {
                subjectIsPlural = false;        // Proper nouns are never plural.
            }
            else if (ptemp == null && ntemp != null)
            {
                subjectIsPlural = ntemp.IsPlural;
            }
            else if (ptemp != null && ntemp == null)
            {
                subjectIsPlural = ptemp.IsPlural;
            }
            else if (ptemp != null && ntemp != null)
            {
                // This probably shouldn't happen, but if it does, we'll take the noun.
                subjectIsPlural = ntemp.IsPlural;
            }
            else
            {
                throw new Exception("Unexpected state.");
            }
            var verbFormToBePlural = subjectIsPlural;

            // Choose how to handle intransitive verbs.
            bool selectTransitive     = true;
            bool removeAccusativeNoun = false;
            bool addPreposition       = false;
            int  choice = 0;

            if (IntransitiveByNoNounClauseFactor > 0 || IntransitiveByPrepositionFactor > 0)
            {
                choice           = randomness.Next(dictionary.CountOf <Verb>()); // Choose between transitive or not by the number of trans/intrans verbs in dictionary.
                selectTransitive = choice < dictionary.CountOfTransitiveVerbs();
                if (!selectTransitive)
                {
                    // OK, so we chose an intransitive verb, how will we handle that?
                    // Note that we've established either IntransitiveByNoNounClauseFactor or IntransitiveByPrepositionFactor is greater than zero, so WeightedCoinFlip() will never throw.
                    bool handleIntransByNoObjectNoun = randomness.WeightedCoinFlip(IntransitiveByNoNounClauseFactor, IntransitiveByPrepositionFactor);
                    if (handleIntransByNoObjectNoun)
                    {
                        // Remove the noun clause.
                        removeAccusativeNoun = true;
                    }
                    else
                    {
                        // Add a preposition.
                        addPreposition = true;
                    }
                }
            }

            bool makeInterrogative = (InterrogativeFactor + NoInterrogativeFactor > 0) &&   // Case where neither is specified: assume no interrogative.
                                     randomness.WeightedCoinFlip(InterrogativeFactor, NoInterrogativeFactor);

            if (makeInterrogative && containsDirectSpeech)
            {
                // Insert an interrogative template after the direct speech verb.
                currentTemplate.Insert(speechVerbIdx + 1, new InterrogativeTemplate(subjectIsPlural));
            }
            else if (makeInterrogative && !containsDirectSpeech)
            {
                // Insert an interrogative template at the start of the phrase.
                currentTemplate.Insert(0, new InterrogativeTemplate(subjectIsPlural));
            }

            // Include adverb?
            bool includeAdverb = (AdverbFactor + NoAdverbFactor > 0) &&     // Case where neither is specified: assume no adverb.
                                 randomness.WeightedCoinFlip(AdverbFactor, NoAdverbFactor);
            bool includeAdverbBeforeVerb = randomness.CoinFlip();

            if (includeAdverb && includeAdverbBeforeVerb)
            {
                currentTemplate.Add(new AdverbTemplate());
            }

            // Select a verb tense form.
            this.BuildTable();
            choice = randomness.Next(this.DistributionMax);
            var tense = VerbTense.Present;

            if (!makeInterrogative)
            {
                // The the verb form becomes present plural whenever an interrogative is used.
                tense = this.LookupTenseFromChoice(choice);
            }
            if (makeInterrogative)
            {
                verbFormToBePlural = true;
            }
            currentTemplate.Add(new VerbTemplate(tense, verbFormToBePlural, selectTransitive));

            // Include adverb after the verb.
            if (includeAdverb && !includeAdverbBeforeVerb)
            {
                currentTemplate.Add(new AdverbTemplate());
            }

            // Add a preposition to make the intransitive verb work?
            if (addPreposition)
            {
                currentTemplate.Add(new PrepositionTemplate());
            }

            // Signal to the second pass we're going to remove the accusative noun clause.
            if (removeAccusativeNoun)
            {
                _LastVerbTemplateIndex = currentTemplate.Count - 1;
            }
        }
 public static T ChooseWord <T>(this WordDictionary dict, Random.RandomSourceBase randomness, IEnumerable <Word> alreadyChosen) where T : Word
 {
     return(ChooseWord <T>(dict, randomness, alreadyChosen, (w) => true));
 }