Observational Bias traits

Announcements, support questions, and discussion for Love/Hate.
Post Reply
FrostedLink
Posts: 12
Joined: Fri Jan 07, 2022 7:43 pm

Observational Bias traits

Post by FrostedLink »

I'm still working out a sample but wanted to get your opinion on this.

The current relationship engine seems focused on the intrinsic value of a deed. This intrinsic value is interpreted and shared amongst FactionMembers.

I don't see a good way to model this:
Observers of a deed skew their perception of a deed based on observable characteristics of the actor performing the deed.

For a concrete example, imagine a world where Cybernetic implants are common. Some actors prefer interacting with non-cybernetic actors.
When an actor with cybernetic implants interacts with them, their PAD is adjusted differently than with a non-cybernetic actor.

From my understanding, Deed 'Personality Traits' don't work here. Using them will disrupt the DefaultEvaluateRumor, especially around TraitAlignment. Specifying a 'Prefers Cybernetic' personality trait doesn't work quite right. The Deed isn't 'Cybernetic' the Actor is.

Likewise, a new Relationship Trait gets ambiguous. Does the faction 'Like Cybernetics'? How does a faction 'Have Cybernetics' and 'Prefer non-Cybernetics'?

I'm working out a 'bias' system where actors can outwardly present an attribute, and prefer an attribute. These are 2 separate values for each attribute.
User avatar
Tony Li
Posts: 20767
Joined: Thu Jul 18, 2013 1:27 pm

Re: Observational Bias traits

Post by Tony Li »

What if you define a Cybernetics personality trait that represents how cybernetic a character is, and then override EvaluateRumor to take the deed actor's Cybernetics trait into account?

I'll make FactionMember.GetAffinity() virtual in the next update. Then you might not need to account for Cybernetics in EvaluateRumor. Instead, GetAffinity() could adjust its return value based on the subject's Cybernetics trait.

It might help to have two personality traits:
  • Cybernetics: How cybernetic a character is
  • Cyberfriendliness: How a character feels about cybernetics
The combination could prove interesting. A character might be heavily modified (Cybernetics +100) but also hate themselves for it (Cyberfriendliness -100). Or a character might have a fetish for cyborgs (Cyberfriendliness +100) even thought they themselves are unmodified (Cybernetics -100).
FrostedLink
Posts: 12
Joined: Fri Jan 07, 2022 7:43 pm

Re: Observational Bias traits

Post by FrostedLink »

actor(A) - highly cybernetic, prefers cybernetics
actor(B) - not cybernetic, prefers cybernetics
actor(C) - not cybernetic, distrusts cybernetics.
actor(D) - highly cybernetic, distrusts cybernetics.

I like this idea around a virtual GetAffinity(). It ties directly into both the source and target of a rumor.
case 1:
actor(A) does some deed to actor(B)
actor(B) tells actor(C) about it.
Actor(C) has a bias against the actor(A), Actor(C) trusts the source(B), but has a lower affinity to actor(A)

case 2:
actor(A) does some deed to actor(B)
actor(C) observes it
Actor(C) has no bias against themselves actor(C), Actor(C) trusts the source(C), but has a lower affinity to actor(A)

case 3:
actor(A) does some deed to actor(B)
actor(D) observes it
Actor(D) has a bias against themselves actor(D), Actor(C) distrusts the source(D), and has a lower affinity to actor(A)

So, I'm not sure that case 3 is fully realized. It seems a bit awkward. You might be able to get around it with a specialized check for a 'has attribute, but prefers the opposite' in the GetTrustInSource delegate.
What if you define a Cybernetics personality trait that represents how cybernetic a character is, and then override EvaluateRumor to take the deed actor's Cybernetics trait into account?
The way I saw this approach is that it completely breaks the trait alignment feature. Or, maybe you mean adding a personality trait and always setting it to '0' in the DeedTemplates. A Deed (action) does not have a bias, the observer and actor do.

Here is a screenshot of the data view I've been thinking of. The formulas aren't quite right yet. But, I do think it is a natural way to think of the problem from the faction's perspective than putting it into the personality traits that are shared with Deeds.
Attachments
love_hate_bias.jpg
love_hate_bias.jpg (293.77 KiB) Viewed 3760 times
User avatar
Tony Li
Posts: 20767
Joined: Thu Jul 18, 2013 1:27 pm

Re: Observational Bias traits

Post by Tony Li »

Bias traits won't make it into the next release, but I'll look into ways to either implement it or support inheritance for custom implementations.
FrostedLink
Posts: 12
Joined: Fri Jan 07, 2022 7:43 pm

Re: Observational Bias traits

Post by FrostedLink »

Is there a mechanism in place to support custom factions?
something like Bias_Faction.

I've attempted to add this, but the FindRelativeProperty doesn't seem to be able to downcast FactionDatabase>factions[]; even when I've overriden it in a Bias_FactionDatabase.

I think this is the last piece of the puzzle, then I'm happy to DM my code over to you. I think you'd prefer that over pasting a non-trivial chunk of the FactionDatabaseEditor.cs source here.
User avatar
Tony Li
Posts: 20767
Joined: Thu Jul 18, 2013 1:27 pm

Re: Observational Bias traits

Post by Tony Li »

That's a difficult one. This patch has two changes:
  • Rumors now receive the same DeedCategory as their original Deeds
  • All methods in FactionDatabaseEditor are now virtual so you can override them
LoveHate_1_10_23.Patch_2022-01-12.unitypackage

---

The way Unity serializes assets, it's not really possible to make a subclass of Faction that FactionDatabase can use as-is. The Faction class is a plain C# class, not a separate ScriptableObject.

One possible solution is to add bias data in a FactionDatabase subclass. Currently, FactionDatabase has a factions[] array and a personalityTraitDefinitions[] array:

Code: Select all

public class FactionDatabase : ScriptableObject
{
    public TraitDefinition[] personalityTraitDefinitions;
    ...
    public Faction[] factions;
    ...
You could add corresponding arrays of bias data and bias traits to your FactionDatabase subclass:

Code: Select all

public class BiasFactionDatabase : FactionDatabase
{
    public TraitDefinition[] personalityTraitDefinitions;
    public TraitDefinition[] biasTraitDefinitions;
    ...
    public Faction[] factions;
    public Bias[] biases; // Should be same length as factions[]
    ...

    GetBiasTrait(string factionName, string biasTraitName)
    {
        // (Pseudocode: return biases[factionName].biasTraitName)
    }
Then make a subclass of FactionDatabaseEditor that

Code: Select all

[CustomEditor(typeof(BiasFactionDatabase), true)]
public class BiasFactionDatabaseEditor : FactionDatabaseEditor
{
    protected override void OnAddFaction(ReorderableList list)
    {
        base.OnAddFaction(list);
        // (Added faction, so need to add corresponding element to biases[])
    }
    
    protected override void OnRemoveFaction(ReorderableList list)
    {
        base.OnRemoveFaction(list);
        // (Removed faction, so need to remove corresponding element from biases[])
    }
    
    // (Also need to handle reordering factions)
    
    protected override void SetupFactionEditList(SerializedProperty faction)
    {
        base.SetupFactionEditList(faction);
        // (Also set up list for Bias data here)
    }
    
    protected virtual void DrawFactionEditSection()
    {
        base.DrawFactionEditSection();
        // (Now draw Bias editor fields for currently-selected faction)
    }
}
FrostedLink
Posts: 12
Joined: Fri Jan 07, 2022 7:43 pm

Re: Observational Bias traits

Post by FrostedLink »

Thanks, i'll have to think on this one more.

I've already applied the patch, it was mostly what I had already considered.

You may also want to add this to FactionDatabase, It helps child classes only call the prompt a single time. Then we do our cleanup after base.RemoveFaction:

Code: Select all

        
        private void OnRemoveFaction(ReorderableList list)
        {
            var factionName = list.serializedProperty.GetArrayElementAtIndex(list.index).FindPropertyRelative("name").stringValue;
            if (EditorUtility.DisplayDialog("Delete selected faction?", factionName, "Delete", "Cancel"))
            {
                RemoveFaction(list);
            }
        }

        protected virtual void RemoveFaction(ReorderableList list){
            var faction = serializedObject.FindProperty("factions").GetArrayElementAtIndex(list.index);
            if (faction != null)
            {
                var factionID = m_factionList.serializedProperty.GetArrayElementAtIndex(m_factionList.index).FindPropertyRelative("id").intValue;
                NotifyFactionsRemoveFaction(factionID);
            }
            ReorderableList.defaultBehaviours.DoRemoveButton(list);
            m_factionTraitList = null;
        }
User avatar
Tony Li
Posts: 20767
Joined: Thu Jul 18, 2013 1:27 pm

Re: Observational Bias traits

Post by Tony Li »

Good idea. I'll add that.
Post Reply