/// <summary> /// Try to add a modifier to a lexica /// </summary> /// <param name="modifier">the lexica that is the modifier</param> /// <returns>Whether or not it succeeded</returns> public ILexica TryModify(ILexica modifier, bool passthru = false) { HashSet <ILexica> newModifiers = new HashSet <ILexica>(Modifiers); if (!newModifiers.Contains(modifier)) { if (modifier.Context == null) { modifier.Context = Context.Clone(); } else { //Sentence must maintain the same observer, language, tense and personage modifier.Context.Language = Context.Language; modifier.Context.Tense = Context.Tense; modifier.Context.Perspective = Context.Perspective; modifier.Context.Observer = Context.Observer; } newModifiers.Add(modifier); Modifiers = newModifiers; } return(passthru ? this : modifier); }
/// <summary> /// -99 = null input /// -1 = wrong type /// 0 = same type, wrong id /// 1 = same reference (same id, same type) /// </summary> /// <param name="obj"></param> /// <returns></returns> public int CompareTo(ILexica other) { if (other != null) { try { if (other.GetType() != GetType()) { return(-1); } if (other.Phrase.Equals(Phrase) && other.Type == Type) { return(1); } return(0); } catch (Exception ex) { LoggingUtility.LogError(ex); } } return(-99); }
/// <summary> /// Alter the lex entirely including all of its sublex /// </summary> /// <param name="context">Contextual nature of the request.</param> /// <param name="obfuscationLevel">-100 to 100 range.</param> /// <returns>the new lex</returns> private ILexica Mutate(MessagingType sensoryType, short obfuscationLevel = 0) { IDictata dict = GetDictata(); ILexica newLex = Clone(); if (dict != null) { IDictata newDict = null; if (obfuscationLevel != 0) { newDict = Thesaurus.ObscureWord(dict, obfuscationLevel); } else if (Type != LexicalType.ProperNoun && (Context.Severity + Context.Elegance + Context.Quality > 0 || Context.Language != dict.Language || Context.Plural != dict.Plural || Context.Possessive != dict.Possessive || Context.Tense != dict.Tense || Context.Perspective != dict.Perspective || Context.Determinant != dict.Determinant || Context.GenderForm.Feminine != dict.Feminine)) { newDict = Thesaurus.GetSynonym(dict, Context); } if (newDict != null) { newLex.Phrase = newDict.Name; } } return(newLex); }
private bool CheckPivotValidity(ILexica first, ILexica second) { return(first?.Context != null && second?.Context != null && first.Context.Position == second.Context.Position && first.Context.Tense == second.Context.Tense && PivotMatch == first.Phrase.Equals(second.Phrase, StringComparison.InvariantCultureIgnoreCase)); }
/// <summary> /// Make a dictata from a lexica /// </summary> /// <param name="lexica">the incoming lexica phrase</param> public Dictata(ILexica lexica) { Name = ""; Antonyms = new HashSet <IDictata>(); Synonyms = new HashSet <IDictata>(); PhraseAntonyms = new HashSet <IDictataPhrase>(); PhraseSynonyms = new HashSet <IDictataPhrase>(); Semantics = new HashSet <string>(); IGlobalConfig globalConfig = ConfigDataCache.Get <IGlobalConfig>(new ConfigDataCacheKey(typeof(IGlobalConfig), "LiveSettings", ConfigDataType.GameWorld)); if (lexica.Context?.Language == null) { if (globalConfig?.BaseLanguage == null) { Language = ConfigDataCache.GetAll <ILanguage>().FirstOrDefault(); } else { Language = globalConfig.BaseLanguage; } } else { Language = lexica.Context.Language; } ILexeme maybeLex = ConfigDataCache.Get <ILexeme>( new ConfigDataCacheKey(typeof(ILexeme), string.Format("{0}_{1}", Language.Name, lexica.Phrase), ConfigDataType.Dictionary)); if (maybeLex == null) { Name = lexica.Phrase; WordType = lexica.Type; } else if (maybeLex.WordForms.Any(form => form.WordType == lexica.Type)) { IDictata wordForm = maybeLex.WordForms.FirstOrDefault(form => form.WordType == lexica.Type); Name = lexica.Phrase; WordType = lexica.Type; Synonyms = wordForm.Synonyms; Antonyms = wordForm.Antonyms; PhraseSynonyms = wordForm.PhraseSynonyms; PhraseAntonyms = wordForm.PhraseAntonyms; Determinant = wordForm.Determinant; Elegance = wordForm.Elegance; Feminine = wordForm.Feminine; Perspective = wordForm.Perspective; Plural = wordForm.Plural; Positional = wordForm.Positional; Possessive = wordForm.Possessive; Quality = wordForm.Quality; Semantics = wordForm.Semantics; Severity = wordForm.Severity; Tense = wordForm.Tense; } }
/// <summary> /// Verify the dictionary has this word already /// </summary> /// <param name="lexica">lexica to check</param> public static void VerifyLexeme(ILexica lexica) { if (lexica == null || string.IsNullOrWhiteSpace(lexica.Phrase) || lexica.Phrase.IsNumeric()) { //we dont want numbers getting in the dict, thats bananas return; } VerifyLexeme(lexica.GetDictata().GetLexeme()); }
public LexicalSentence(ILexica lex) { Modifiers = new List <Tuple <ISensoryEvent, short> >(); Subject = new List <Tuple <ISensoryEvent, short> >(); Predicate = new List <Tuple <ISensoryEvent, short> >(); Type = SentenceType.Statement; SensoryType = MessagingType.Visible; SetLanguage(lex.Context?.Language); AddEvent(new SensoryEvent(lex, 30, SensoryType)); }
/// <summary> /// Does this lexica match the rule /// </summary> /// <param name="word">The lex</param> /// <returns>if it matches</returns> public bool Matches(ILexica lex) { string[] fromBegins = FromBeginsWith.Split('|', StringSplitOptions.RemoveEmptyEntries); string[] fromEnds = FromEndsWith.Split('|', StringSplitOptions.RemoveEmptyEntries); return((fromBegins.Count() == 0 || fromBegins.Any(bw => lex.Phrase.StartsWith(bw))) && (fromEnds.Count() == 0 || fromEnds.Any(bw => lex.Phrase.EndsWith(bw))) && (Tense == LexicalTense.None || lex.Context.Tense == Tense) && (Perspective == NarrativePerspective.None || lex.Context.Perspective == Perspective) && (!WhenPlural || lex.Context.Plural) && (!WhenPossessive || lex.Context.Possessive) && (SpecificWord == null || SpecificWord.Equals(lex.GetDictata())) && (SpecificWord != null || ((FromRole == GrammaticalType.None || FromRole == lex.Role) && (FromType == LexicalType.None || FromType == lex.Type)))); }
/// <summary> /// Verify the dictionary has this word already /// </summary> /// <param name="lexica">lexica to check</param> public static void VerifyLexeme(ILexica lexica) { if (string.IsNullOrWhiteSpace(lexica.Phrase) || lexica.Phrase.IsNumeric()) { //we dont want numbers getting in the dict, thats bananas return; } //Experiment: make new everything if (VerifyLexeme(lexica.GetDictata().GetLexeme()) != null) { //make a new one lexica.GenerateDictata(); } }
/// <summary> /// Compares this object to another one to see if they are the same object /// </summary> /// <param name="other">the object to compare to</param> /// <returns>true if the same object</returns> public bool Equals(ILexica other) { if (other != default(ILexica)) { try { return(other.Phrase.Equals(Phrase) && other.Type == Type); } catch (Exception ex) { LoggingUtility.LogError(ex); } } return(false); }
private ILexica RunObscura(MessagingType sensoryType, IEntity observer, bool over) { ILexica message = null; LexicalContext context = new LexicalContext(observer) { Determinant = true, Perspective = NarrativePerspective.FirstPerson, Position = LexicalPosition.Around }; switch (sensoryType) { case MessagingType.Audible: if (!over) { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "hear", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "sounds", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "soft", context)); } else { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "hear", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "sounds", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "loud", context)); } break; case MessagingType.Olefactory: if (!over) { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "smell", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "something", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "subtle", context)); } else { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "smell", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "something", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "pungent", context)); } break; case MessagingType.Psychic: if (!over) { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "sense", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "presence", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "vague", context)); } else { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "sense", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "presence", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "disturbing", context)); } break; case MessagingType.Tactile: context.Position = LexicalPosition.Attached; if (!over) { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "brushes", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "skin", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "lightly", context)); } else { context.Elegance = -5; message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "rubs", observer, observer) .TryModify(new Lexica(LexicalType.Pronoun, GrammaticalType.Subject, "you", context)); } break; case MessagingType.Taste: context.Position = LexicalPosition.InsideOf; if (!over) { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "taste", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "something", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "subtle", context)); } else { context.Elegance = -5; message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "taste", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "something", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "offensive", context)); } break; case MessagingType.Visible: context.Plural = true; if (!over) { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "see", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "shadows", context)); } else { message = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "see", observer, observer) .TryModify(new Lexica(LexicalType.Noun, GrammaticalType.Subject, "lights", context)) .TryModify(new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, "blinding", context)); } break; } return(message); }
/// <summary> /// Unpack the lexica /// </summary> public IEnumerable <ISensoryEvent> Unpack() { List <Tuple <ISensoryEvent, int> > wordList = new List <Tuple <ISensoryEvent, int> >(); //Subject foreach (Tuple <ISensoryEvent, short> lex in Subject.OrderBy(pair => pair.Item2)) { IEnumerable <ILexica> lexes = lex.Item1.Event.Unpack(lex.Item1.SensoryType, lex.Item1.Strength); int i = (lex.Item2 * 100) + -10000; foreach (ILexica subLex in lexes) { wordList.Add(new Tuple <ISensoryEvent, int>(new SensoryEvent(subLex, lex.Item1.Strength, lex.Item1.SensoryType), i++)); } } //Predicate foreach (Tuple <ISensoryEvent, short> lex in Predicate.OrderBy(pair => pair.Item2)) { IEnumerable <ILexica> lexes = lex.Item1.Event.Unpack(lex.Item1.SensoryType, lex.Item1.Strength); int i = (lex.Item2 + 1) * 100; foreach (ILexica subLex in lexes) { wordList.Add(new Tuple <ISensoryEvent, int>(new SensoryEvent(subLex, lex.Item1.Strength, lex.Item1.SensoryType), i++)); } } //Modifiers foreach (Tuple <ISensoryEvent, short> lex in Modifiers.OrderBy(pair => pair.Item2)) { IEnumerable <ILexica> lexes = lex.Item1.Event.Unpack(lex.Item1.SensoryType, lex.Item1.Strength); int i = (lex.Item2 * 100) + 10000; foreach (ILexica subLex in lexes) { wordList.Add(new Tuple <ISensoryEvent, int>(new SensoryEvent(subLex, lex.Item1.Strength, lex.Item1.SensoryType), i++)); } } //Transformational word pair rules foreach (IDictataTransformationRule rule in Language.TransformationRules.Where(rul => rul.TransformedWord != null && wordList.Any(pair => rul.Origin.Equals(pair.Item1.Event.GetDictata())))) { string[] beginsWith = rule.BeginsWith.Split('|', StringSplitOptions.RemoveEmptyEntries); string[] endsWith = rule.EndsWith.Split('|', StringSplitOptions.RemoveEmptyEntries); foreach (Tuple <ISensoryEvent, int> lexPair in wordList.Where(pair => rule.Origin.Equals(pair.Item1.Event.GetDictata()))) { ILexica lex = lexPair.Item1.Event; Tuple <ISensoryEvent, int> nextEvent = wordList.OrderBy(word => word.Item2).FirstOrDefault(word => word.Item2 > lexPair.Item2); if (nextEvent == null) { continue; } ILexica nextLex = nextEvent.Item1.Event; if ((rule.SpecificFollowing == null || nextLex.GetDictata().Equals(rule.SpecificFollowing)) && (beginsWith.Count() == 0 || beginsWith.Any(bw => nextLex.Phrase.StartsWith(bw))) && (endsWith.Count() == 0 || endsWith.Any(ew => nextLex.Phrase.EndsWith(ew)))) { lex.Phrase = rule.TransformedWord.Name; } } } return(wordList.OrderBy(words => words.Item2).Select(words => words.Item1)); }
/// <summary> /// Render this in a short descriptive style /// </summary> /// <param name="viewer">The entity looking</param> /// <returns>the output strings</returns> public override ILexicalParagraph GetFullDescription(IEntity viewer, MessagingType[] sensoryTypes = null) { if (sensoryTypes == null || sensoryTypes.Count() == 0) { sensoryTypes = new MessagingType[] { MessagingType.Audible, MessagingType.Olefactory, MessagingType.Psychic, MessagingType.Tactile, MessagingType.Taste, MessagingType.Visible }; } LexicalContext collectiveContext = new LexicalContext(viewer) { Determinant = true, Perspective = NarrativePerspective.SecondPerson, Plural = false, Position = LexicalPosition.None, Tense = LexicalTense.Present }; LexicalContext discreteContext = new LexicalContext(viewer) { Determinant = false, Perspective = NarrativePerspective.ThirdPerson, Plural = false, Position = LexicalPosition.Far, Tense = LexicalTense.Present }; //Self becomes the first sense in the list List <ISensoryEvent> sensoryOutput = new List <ISensoryEvent>(); foreach (MessagingType sense in sensoryTypes) { ISensoryEvent me = GetSelf(sense); switch (sense) { case MessagingType.Audible: me.Strength = GetAudibleDelta(viewer); IEnumerable <ISensoryEvent> aDescs = GetAudibleDescriptives(viewer); if (aDescs.Count() == 0) { continue; } me.TryModify(aDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); ILexica uberSounds = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "hear", collectiveContext); uberSounds.TryModify(aDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in aDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberSounds.TryModify(newDesc); } if (uberSounds.Modifiers.Any()) { me.TryModify(uberSounds); } break; case MessagingType.Olefactory: me.Strength = GetOlefactoryDelta(viewer); IEnumerable <ISensoryEvent> oDescs = GetOlefactoryDescriptives(viewer); if (oDescs.Count() == 0) { continue; } me.TryModify(oDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); ILexica uberSmells = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "smell", collectiveContext); uberSmells.TryModify(oDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in oDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberSmells.TryModify(newDesc); } if (uberSmells.Modifiers.Any()) { me.TryModify(uberSmells); } break; case MessagingType.Psychic: me.Strength = GetPsychicDelta(viewer); IEnumerable <ISensoryEvent> pDescs = GetPsychicDescriptives(viewer); if (pDescs.Count() == 0) { continue; } me.TryModify(pDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); Lexica collectivePsy = new Lexica(LexicalType.Pronoun, GrammaticalType.Subject, "you", collectiveContext); ILexica uberPsy = collectivePsy.TryModify(LexicalType.Verb, GrammaticalType.Verb, "sense"); uberPsy.TryModify(pDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in pDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberPsy.TryModify(newDesc); } if (uberPsy.Modifiers.Any()) { me.TryModify(collectivePsy); } break; case MessagingType.Taste: continue; case MessagingType.Tactile: me.Strength = GetTactileDelta(viewer); //Add the temperature me.TryModify(LexicalType.Verb, GrammaticalType.Verb, "feels").TryModify(new Lexica[] { new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, MeteorologicalUtilities.ConvertHumidityToType(EffectiveHumidity()).ToString(), collectiveContext), new Lexica(LexicalType.Adjective, GrammaticalType.Descriptive, MeteorologicalUtilities.ConvertTemperatureToType(EffectiveTemperature()).ToString(), collectiveContext) }); break; case MessagingType.Visible: me.Strength = GetVisibleDelta(viewer); IEnumerable <ISensoryEvent> vDescs = GetVisibleDescriptives(viewer); if (vDescs.Count() > 0) { me.TryModify(vDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); Lexica collectiveSight = new Lexica(LexicalType.Pronoun, GrammaticalType.Subject, "you", collectiveContext); ILexica uberSight = collectiveSight.TryModify(LexicalType.Verb, GrammaticalType.Verb, "see"); uberSight.TryModify(vDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in vDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberSight.TryModify(newDesc); } if (uberSight.Modifiers.Any()) { me.TryModify(collectiveSight); } } //Describe the size and population of this zone DimensionalSizeDescription zoneSize = GeographicalUtilities.ConvertSizeToType(GetModelDimensions(), GetType()); me.TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, zoneSize.ToString()); //Render people in the zone CrowdSizeDescription populationSize = GeographicalUtilities.GetCrowdSize(GetContents <IMobile>().Count()); string crowdSize = "abandoned"; if ((short)populationSize > (short)zoneSize) { crowdSize = "crowded"; } else if (populationSize > CrowdSizeDescription.Intimate) { crowdSize = "sparsely populated"; } me.TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, crowdSize); break; } if (me != null) { sensoryOutput.Add(me); } } foreach (ICelestial celestial in GetVisibileCelestials(viewer)) { sensoryOutput.AddRange(celestial.RenderAsContents(viewer, sensoryTypes).Events); } foreach (IWeatherEvent wEvent in WeatherEvents) { sensoryOutput.AddRange(wEvent.RenderAsContents(viewer, sensoryTypes).Events); } foreach (INaturalResourceSpawn <IFlora> resource in FloraNaturalResources) { sensoryOutput.AddRange(resource.Resource.RenderResourceCollection(viewer, resource.RateFactor).Events); } foreach (INaturalResourceSpawn <IFauna> resource in FaunaNaturalResources) { sensoryOutput.AddRange(resource.Resource.RenderResourceCollection(viewer, resource.RateFactor).Events); } foreach (INaturalResourceSpawn <IMineral> resource in MineralNaturalResources) { sensoryOutput.AddRange(resource.Resource.RenderResourceCollection(viewer, resource.RateFactor).Events); } //render our locales out foreach (ILocale locale in LiveCache.GetAll <ILocale>().Where(loc => loc.ParentLocation?.TemplateId == TemplateId)) { sensoryOutput.AddRange(locale.RenderAsContents(viewer, sensoryTypes).Events); } //render our locales out foreach (IPathway path in GetPathways()) { sensoryOutput.AddRange(path.RenderAsContents(viewer, sensoryTypes).Events); } return(new LexicalParagraph(sensoryOutput)); }
/// <summary> /// Render this as being show inside a container /// </summary> /// <param name="viewer">The entity looking</param> /// <returns>the output strings</returns> public override ILexicalParagraph RenderAsContents(IEntity viewer, MessagingType[] sensoryTypes) { if (sensoryTypes == null || sensoryTypes.Count() == 0) { sensoryTypes = new MessagingType[] { MessagingType.Audible, MessagingType.Olefactory, MessagingType.Psychic, MessagingType.Tactile, MessagingType.Taste, MessagingType.Visible }; } LexicalContext collectiveContext = new LexicalContext(viewer) { Determinant = true, Perspective = NarrativePerspective.SecondPerson, Plural = false, Position = LexicalPosition.None, Tense = LexicalTense.Present }; LexicalContext discreteContext = new LexicalContext(viewer) { Determinant = false, Perspective = NarrativePerspective.ThirdPerson, Plural = false, Position = LexicalPosition.Far, Tense = LexicalTense.Present }; List <ISensoryEvent> sensoryOutput = new List <ISensoryEvent>(); foreach (MessagingType sense in sensoryTypes) { SensoryEvent me = new SensoryEvent(new Lexica(LexicalType.Pronoun, GrammaticalType.Subject, "you", collectiveContext), 0, sense); ILexica senseVerb = null; IEnumerable <ISensoryEvent> senseDescs = Enumerable.Empty <ISensoryEvent>(); switch (sense) { case MessagingType.Audible: me.Strength = GetAudibleDelta(viewer); senseVerb = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "hear", collectiveContext); IEnumerable <ISensoryEvent> audibleDescs = GetAudibleDescriptives(viewer); if (audibleDescs.Count() == 0) { continue; } ISensoryEvent audibleNoun = null; if (!audibleDescs.Any(desc => desc.Event.Role == GrammaticalType.DirectObject)) { audibleNoun = new SensoryEvent(new Lexica(LexicalType.Noun, GrammaticalType.DirectObject, "noise", discreteContext), me.Strength, sense); } else { audibleNoun = audibleDescs.FirstOrDefault(desc => desc.Event.Role == GrammaticalType.DirectObject); } audibleNoun.TryModify(audibleDescs.Where(desc => desc.Event.Role == GrammaticalType.Descriptive)); senseDescs = new List <ISensoryEvent>() { audibleNoun }; break; case MessagingType.Olefactory: me.Strength = GetOlefactoryDelta(viewer); senseVerb = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "smell", collectiveContext); IEnumerable <ISensoryEvent> smellDescs = GetOlefactoryDescriptives(viewer); if (smellDescs.Count() == 0) { continue; } ISensoryEvent smellNoun = null; if (!smellDescs.Any(desc => desc.Event.Role == GrammaticalType.DirectObject)) { smellNoun = new SensoryEvent(new Lexica(LexicalType.Noun, GrammaticalType.DirectObject, "odor", discreteContext), me.Strength, sense); } else { smellNoun = smellDescs.FirstOrDefault(desc => desc.Event.Role == GrammaticalType.DirectObject); } smellNoun.TryModify(smellDescs.Where(desc => desc.Event.Role == GrammaticalType.Descriptive)); senseDescs = new List <ISensoryEvent>() { smellNoun }; break; case MessagingType.Psychic: me.Strength = GetPsychicDelta(viewer); senseVerb = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "sense", collectiveContext); IEnumerable <ISensoryEvent> psyDescs = GetPsychicDescriptives(viewer); if (psyDescs.Count() == 0) { continue; } ISensoryEvent psyNoun = null; if (!psyDescs.Any(desc => desc.Event.Role == GrammaticalType.DirectObject)) { psyNoun = new SensoryEvent(new Lexica(LexicalType.Noun, GrammaticalType.DirectObject, "presence", discreteContext), me.Strength, sense); } else { psyNoun = psyDescs.FirstOrDefault(desc => desc.Event.Role == GrammaticalType.DirectObject); } psyNoun.TryModify(psyDescs.Where(desc => desc.Event.Role == GrammaticalType.Descriptive)); senseDescs = new List <ISensoryEvent>() { psyNoun }; break; case MessagingType.Tactile: case MessagingType.Taste: continue; case MessagingType.Visible: me.Strength = GetVisibleDelta(viewer); senseVerb = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "see", collectiveContext); IEnumerable <ISensoryEvent> seeDescs = GetVisibleDescriptives(viewer); if (seeDescs.Count() == 0) { continue; } ISensoryEvent seeNoun = null; if (!seeDescs.Any(desc => desc.Event.Role == GrammaticalType.DirectObject)) { seeNoun = new SensoryEvent(new Lexica(LexicalType.Noun, GrammaticalType.DirectObject, "thing", discreteContext), me.Strength, sense); } else { seeNoun = seeDescs.FirstOrDefault(desc => desc.Event.Role == GrammaticalType.DirectObject); } seeNoun.TryModify(seeDescs.Where(desc => desc.Event.Role == GrammaticalType.Descriptive)); senseDescs = new List <ISensoryEvent>() { seeNoun }; break; } if (senseVerb != null && senseDescs.Count() > 0) { IEnumerable <ILexica> senseEvents = senseDescs.Select(desc => desc.Event); foreach (ILexica evt in senseEvents) { evt.Context = discreteContext; senseVerb.TryModify(evt); } me.TryModify(senseVerb); sensoryOutput.Add(me); } } return(new LexicalParagraph(sensoryOutput)); }
/// <summary> /// Create a narrative description from this /// </summary> /// <param name="overridingContext">Context to override the lexica with</param> /// <param name="anonymize">Should we omit the proper name of the initial subject entirely (and only resort to pronouns)</param> /// <returns>A long description</returns> public IEnumerable <ILexicalSentence> Unpack(LexicalContext overridingContext = null, bool anonymize = false) { List <ILexicalSentence> sentences = new List <ILexicalSentence>(); //short circuit empty lexica if (string.IsNullOrWhiteSpace(Event?.Phrase)) { return(sentences); } if (overridingContext != null) { //Sentence must maintain the same language, tense and personage as well as the weight values Event.Context.Language = overridingContext.Language; Event.Context.Tense = overridingContext.Tense; Event.Context.Perspective = overridingContext.Perspective; Event.Context.Elegance = overridingContext.Elegance; Event.Context.Severity = overridingContext.Severity; Event.Context.Quality = overridingContext.Quality; } //Language rules engine, default to base language if we have an empty language if (Event.Context.Language == null || (Event.Context.Language?.WordPairRules?.Count == 0 && Event.Context.Language?.WordRules?.Count == 0)) { IGlobalConfig globalConfig = ConfigDataCache.Get <IGlobalConfig>(new ConfigDataCacheKey(typeof(IGlobalConfig), "LiveSettings", ConfigDataType.GameWorld)); Event.Context.Language = globalConfig.BaseLanguage; } if (anonymize) { LexicalContext pronounContext = Event.Context.Clone(); pronounContext.Perspective = NarrativePerspective.SecondPerson; pronounContext.Position = LexicalPosition.None; pronounContext.Tense = LexicalTense.None; pronounContext.Determinant = false; pronounContext.Semantics = new HashSet <string>(); IDictata pronoun = Thesaurus.GetWord(pronounContext, LexicalType.Pronoun); Event.Phrase = pronoun.Name; Event.Type = LexicalType.Pronoun; } List <ILexica> subjects = new List <ILexica> { Event }; subjects.AddRange(Event.Modifiers.Where(mod => mod != null && mod.Role == GrammaticalType.Subject)); Event.Modifiers.RemoveWhere(mod => mod == null || mod.Role == GrammaticalType.Subject); foreach (ILexica subject in subjects) { //This is to catch directly described entities, we have to add a verb to it for it to make sense. "Complete sentence rule" if (subject.Modifiers.Any() && !subject.Modifiers.Any(mod => mod.Role == GrammaticalType.Verb)) { LexicalContext verbContext = subject.Context.Clone(); verbContext.Semantics = new HashSet <string> { "existential" }; verbContext.Determinant = false; IDictata verb = Thesaurus.GetWord(verbContext, LexicalType.Verb); ILexica verbLex = verb.GetLexica(GrammaticalType.Verb, verbContext); verbLex.TryModify(subject.Modifiers); subject.Modifiers = new HashSet <ILexica>(); subject.TryModify(verbLex); } if (subject.Modifiers.Any(mod => mod.Role == GrammaticalType.Subject)) { sentences.Add(subject.MakeSentence(SentenceType.Partial, SensoryType, Strength)); //fragment sentences foreach (ILexica subLex in subject.Modifiers.Where(mod => mod.Role == GrammaticalType.Subject)) { sentences.Add(subLex.MakeSentence(SentenceType.Statement, SensoryType, Strength)); } } else { //full obfuscation happens at 100 only if (Strength <= -100 || Strength >= 100) { ILexica lex = RunObscura(SensoryType, subject, subject.Context.Observer, Strength > 0); sentences.Add(lex.MakeSentence(SentenceType.Statement, SensoryType, Strength)); } else { sentences.Add(subject.MakeSentence(SentenceType.Statement, SensoryType, Strength)); } } } return(sentences); }
private ILexica RunObscura(MessagingType sensoryType, ILexica subject, IEntity observer, bool over) { LexicalContext context = new LexicalContext(observer) { Determinant = true, Perspective = NarrativePerspective.FirstPerson, Position = LexicalPosition.Around }; subject.Modifiers = new HashSet <ILexica>(); subject.Type = LexicalType.Verb; subject.Role = GrammaticalType.Verb; subject.Context = context; switch (sensoryType) { case MessagingType.Audible: subject.Phrase = "hear"; if (!over) { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "sounds") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "soft"); } else { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "sounds") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "loud"); } break; case MessagingType.Olefactory: subject.Phrase = "smell"; if (!over) { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "something") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "subtle"); } else { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "something") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "pungent"); } break; case MessagingType.Psychic: subject.Phrase = "sense"; if (!over) { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "presence") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "vague"); } else { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "presence") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "disturbing"); } break; case MessagingType.Tactile: subject.Phrase = "brushes"; context.Position = LexicalPosition.Attached; if (!over) { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "skin") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "lightly"); } else { subject.Phrase = "rubs"; context.Elegance = -5; subject.TryModify(LexicalType.Pronoun, GrammaticalType.Subject, "you"); } break; case MessagingType.Taste: subject.Phrase = "taste"; context.Position = LexicalPosition.InsideOf; if (!over) { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "something") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "subtle"); } else { context.Elegance = -5; subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "something") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "offensive"); } break; case MessagingType.Visible: subject.Phrase = "see"; context.Plural = true; if (!over) { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "shadows"); } else { subject.TryModify(LexicalType.Noun, GrammaticalType.Subject, "lights") .TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, "blinding"); } break; } return(subject); }
/// <summary> /// Render this in a short descriptive style /// </summary> /// <param name="viewer">The entity looking</param> /// <returns>the output strings</returns> public override ILexicalParagraph GetFullDescription(IEntity viewer, MessagingType[] sensoryTypes = null) { if (sensoryTypes == null || sensoryTypes.Count() == 0) { sensoryTypes = new MessagingType[] { MessagingType.Audible, MessagingType.Olefactory, MessagingType.Psychic, MessagingType.Tactile, MessagingType.Taste, MessagingType.Visible }; } LexicalContext collectiveContext = new LexicalContext(viewer) { Determinant = true, Perspective = NarrativePerspective.SecondPerson, Plural = false, Position = LexicalPosition.Around, Tense = LexicalTense.Present }; LexicalContext discreteContext = new LexicalContext(viewer) { Determinant = true, Perspective = NarrativePerspective.ThirdPerson, Plural = false, Position = LexicalPosition.Attached, Tense = LexicalTense.Present }; //Self becomes the first sense in the list List <ISensoryEvent> messages = new List <ISensoryEvent>(); foreach (MessagingType sense in sensoryTypes) { ISensoryEvent me = GetSelf(sense); switch (sense) { case MessagingType.Audible: me.Strength = GetAudibleDelta(viewer); IEnumerable <ISensoryEvent> aDescs = GetAudibleDescriptives(viewer); me.TryModify(aDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); ILexica uberSounds = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "hear", collectiveContext); uberSounds.TryModify(aDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in aDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.Subject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); me.TryModify(newDesc); } if (uberSounds.Modifiers.Any(mod => mod.Role == GrammaticalType.Subject)) { me.TryModify(uberSounds); } break; case MessagingType.Olefactory: me.Strength = GetOlefactoryDelta(viewer); IEnumerable <ISensoryEvent> oDescs = GetOlefactoryDescriptives(viewer); me.TryModify(oDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); Lexica uberSmells = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "smell", collectiveContext); uberSmells.TryModify(oDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in oDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberSmells.TryModify(newDesc); } if (uberSmells.Modifiers.Any(mod => mod.Role == GrammaticalType.Subject)) { me.TryModify(uberSmells); } break; case MessagingType.Psychic: me.Strength = GetPsychicDelta(viewer); IEnumerable <ISensoryEvent> pDescs = GetPsychicDescriptives(viewer); me.TryModify(pDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); Lexica collectivePsy = new Lexica(LexicalType.Pronoun, GrammaticalType.Subject, "you", collectiveContext); ILexica uberPsy = collectivePsy.TryModify(LexicalType.Verb, GrammaticalType.Verb, "sense"); uberPsy.TryModify(pDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in pDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberPsy.TryModify(newDesc); } if (uberPsy.Modifiers.Any(mod => mod.Role == GrammaticalType.Subject)) { me.TryModify(collectivePsy); } break; case MessagingType.Taste: me.Strength = GetTasteDelta(viewer); IEnumerable <ISensoryEvent> taDescs = GetTasteDescriptives(viewer); me.TryModify(taDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); Lexica uberTaste = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "taste", collectiveContext); uberTaste.TryModify(taDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in taDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberTaste.TryModify(newDesc); } if (uberTaste.Modifiers.Any(mod => mod.Role == GrammaticalType.Subject)) { me.TryModify(uberTaste); } break; case MessagingType.Tactile: me.Strength = GetTactileDelta(viewer); IEnumerable <ISensoryEvent> tDescs = GetOlefactoryDescriptives(viewer); me.TryModify(tDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); Lexica uberTouch = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "feel", collectiveContext); uberTouch.TryModify(tDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in tDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberTouch.TryModify(newDesc); } if (uberTouch.Modifiers.Any(mod => mod.Role == GrammaticalType.Subject)) { me.TryModify(uberTouch); } break; case MessagingType.Visible: me.Strength = GetVisibleDelta(viewer); IEnumerable <ISensoryEvent> vDescs = GetVisibleDescriptives(viewer); me.TryModify(vDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Descriptive)); Lexica uberSight = new Lexica(LexicalType.Verb, GrammaticalType.Verb, "appears", collectiveContext); uberSight.TryModify(vDescs.Where(adesc => adesc.Event.Role == GrammaticalType.DirectObject).Select(adesc => adesc.Event)); foreach (ISensoryEvent desc in vDescs.Where(adesc => adesc.Event.Role == GrammaticalType.Subject)) { Lexica newDesc = new Lexica(desc.Event.Type, GrammaticalType.DirectObject, desc.Event.Phrase, discreteContext); newDesc.TryModify(desc.Event.Modifiers); uberSight.TryModify(newDesc); } if (uberSight.Modifiers.Any(mod => mod.Role == GrammaticalType.Subject)) { me.TryModify(uberSight); } //Describe the size and population of this zone DimensionalSizeDescription objectSize = GeographicalUtilities.ConvertSizeToType(GetModelDimensions(), GetType()); me.TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, objectSize.ToString()); //Render people in the zone ObjectContainmentSizeDescription bulgeSizeAdjective = GeographicalUtilities.GetObjectContainmentSize(GetContents <IInanimate>().Sum(obj => obj.GetModelVolume()), GetModelVolume()); me.TryModify(LexicalType.Adjective, GrammaticalType.Descriptive, bulgeSizeAdjective.ToString()); break; } messages.Add(me); } return(new LexicalParagraph(messages)); }
public SensoryEvent(ILexica happening, short strength, MessagingType sensoryType) { Event = happening; Strength = strength; SensoryType = sensoryType; }
/// <summary> /// Try to add a modifier to a lexica /// </summary> /// <param name="modifier">the lexica that is the modifier</param> /// <returns>Whether or not it succeeded</returns> public ILexica TryModify(ILexica modifier, bool passthru = false) { return(Event.TryModify(modifier, passthru)); }
/// <summary> /// Unpacks this applying language rules to expand and add articles/verbs where needed /// </summary> /// <param name="overridingContext">The full lexical context</param> /// <returns>A long description</returns> public IEnumerable <ILexica> Unpack(MessagingType sensoryType, short strength, LexicalContext overridingContext = null) { if (overridingContext != null) { IGlobalConfig globalConfig = ConfigDataCache.Get <IGlobalConfig>(new ConfigDataCacheKey(typeof(IGlobalConfig), "LiveSettings", ConfigDataType.GameWorld)); //Sentence must maintain the same language, tense and personage Context.Language = overridingContext.Language ?? Context.Language ?? globalConfig.BaseLanguage; Context.Tense = overridingContext.Tense; Context.Perspective = overridingContext.Perspective; Context.Elegance = overridingContext.Elegance; Context.Severity = overridingContext.Severity; Context.Quality = overridingContext.Quality; } ILexica newLex = Mutate(sensoryType, strength); foreach (IWordRule wordRule in Context.Language.WordRules.Where(rul => rul.Matches(newLex)) .OrderByDescending(rul => rul.RuleSpecificity())) { if (wordRule.NeedsArticle && (!wordRule.WhenPositional || Context.Position != LexicalPosition.None) && !newLex.Modifiers.Any(mod => (mod.Type == LexicalType.Article && !wordRule.WhenPositional && mod.Context.Position == LexicalPosition.None) || (mod.Type == LexicalType.Preposition && wordRule.WhenPositional && mod.Context.Position != LexicalPosition.None))) { LexicalContext articleContext = Context.Clone(); //Make it determinant if the word is plural articleContext.Determinant = Context.Plural || articleContext.Determinant; IDictata article = null; if (wordRule.SpecificAddition != null) { article = wordRule.SpecificAddition; } else { article = Thesaurus.GetWord(articleContext, wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article); } if (article != null && !newLex.Modifiers.Any(lx => article.Name.Equals(lx.Phrase, StringComparison.InvariantCultureIgnoreCase))) { ILexica newArticle = newLex.TryModify(wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article , GrammaticalType.Descriptive, article.Name, false); if (!wordRule.WhenPositional) { newArticle.Context.Position = LexicalPosition.None; } } } else if (wordRule.SpecificAddition != null && !newLex.Modifiers.Any(lx => wordRule.SpecificAddition.Equals(lx.GetDictata()))) { newLex.TryModify(wordRule.SpecificAddition.WordType, GrammaticalType.Descriptive, wordRule.SpecificAddition.Name); } if (!string.IsNullOrWhiteSpace(wordRule.AddPrefix) && !newLex.Phrase.StartsWith(wordRule.AddPrefix)) { newLex.Phrase = string.Format("{0}{1}", wordRule.AddPrefix, newLex.Phrase.Trim()); } if (!string.IsNullOrWhiteSpace(wordRule.AddSuffix) && !newLex.Phrase.EndsWith(wordRule.AddSuffix)) { newLex.Phrase = string.Format("{1}{0}", wordRule.AddSuffix, newLex.Phrase.Trim()); } } //Placement ordering List <Tuple <ILexica, int> > modifierList = new List <Tuple <ILexica, int> > { new Tuple <ILexica, int>(newLex, 0) }; //modification rules ordered by specificity List <ILexica> currentModifiers = new List <ILexica>(newLex.Modifiers); foreach (ILexica modifier in currentModifiers) { foreach (IWordPairRule wordRule in Context.Language.WordPairRules.Where(rul => rul.Matches(newLex, modifier)) .OrderByDescending(rul => rul.RuleSpecificity())) { if (wordRule.NeedsArticle && (!wordRule.WhenPositional || Context.Position != LexicalPosition.None) && !newLex.Modifiers.Any(mod => (mod.Type == LexicalType.Article && !wordRule.WhenPositional && mod.Context.Position == LexicalPosition.None) || (mod.Type == LexicalType.Preposition && wordRule.WhenPositional && mod.Context.Position != LexicalPosition.None))) { LexicalContext articleContext = Context.Clone(); //Make it determinant if the word is plural articleContext.Determinant = Context.Plural || articleContext.Determinant; IDictata article = null; if (wordRule.SpecificAddition != null) { article = wordRule.SpecificAddition; } else { article = Thesaurus.GetWord(articleContext, wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article); } if (article != null && !newLex.Modifiers.Any(lx => article.Name.Equals(lx.Phrase, StringComparison.InvariantCultureIgnoreCase))) { ILexica newArticle = newLex.TryModify(wordRule.WhenPositional ? LexicalType.Preposition : LexicalType.Article , GrammaticalType.Descriptive, article.Name, false); if (!wordRule.WhenPositional) { newArticle.Context.Position = LexicalPosition.None; } } } else if (wordRule.SpecificAddition != null && !newLex.Modifiers.Any(lx => wordRule.SpecificAddition.Equals(lx.GetDictata()))) { newLex.TryModify(wordRule.SpecificAddition.WordType, GrammaticalType.Descriptive, wordRule.SpecificAddition.Name); } if (!string.IsNullOrWhiteSpace(wordRule.AddPrefix) && !newLex.Phrase.StartsWith(wordRule.AddPrefix)) { newLex.Phrase = string.Format("{0}{1}", wordRule.AddPrefix, newLex.Phrase.Trim()); } if (!string.IsNullOrWhiteSpace(wordRule.AddSuffix) && !newLex.Phrase.EndsWith(wordRule.AddSuffix)) { newLex.Phrase = string.Format("{1}{0}", wordRule.AddSuffix, newLex.Phrase.Trim()); } } } foreach (ILexica modifier in newLex.Modifiers) { IWordPairRule rule = Context.Language.WordPairRules.OrderByDescending(rul => rul.RuleSpecificity()) .FirstOrDefault(rul => rul.Matches(newLex, modifier)); if (rule != null) { int i = 0; foreach (ILexica subModifier in modifier.Unpack(sensoryType, strength, overridingContext ?? Context).Distinct()) { modifierList.Add(new Tuple <ILexica, int>(subModifier, rule.ModificationOrder + i++)); } } } return(modifierList.OrderBy(tup => tup.Item2).Select(tup => tup.Item1)); }