-
Notifications
You must be signed in to change notification settings - Fork 0
/
personality.go
166 lines (145 loc) · 4.17 KB
/
personality.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package aifiver
// Personality represents a personality that is a combination of facet scores and
// expressed traits.
type Personality struct {
t *Traiter // Traiter reference for re-evaluating the expressed traits
BigModel // The model which influences which traits are expressed.
Expressed []*Trait // Traits expressed based on the underlying 5 factor model.
// TODO: Proneness to fall victim to cetain fates (accidental death, falling victim to intrigue)
Modifiers []*Modifier // Temporary facet modifiers (Griefing, Recent Betrayal, Setback, ...)
// TODO: Add a factor of how much the modifiers affect the personality...
// Over time this should deminish and eventually disappear.
}
// NewPersonality returns a new, pretty boring personality.
func NewPersonality(t *Traiter) *Personality {
return &Personality{
t: t,
}
}
// NewPersonalityFromPreset returns a new personality based on the given preset.
func NewPersonalityFromPreset(t *Traiter, ps map[Facet]int) *Personality {
p := NewPersonality(t)
for key, val := range ps {
p.BigModel.Facets[key] = val
}
p.Rebuild()
return p
}
// NewPersonalityRandomized returns a new personality with random facet values.
// TODO: Allow custom rand source or seed.
func NewPersonalityRandomized(t *Traiter) *Personality {
p := NewPersonality(t)
p.BigModel = *RandomBig()
p.Rebuild()
return p
}
// AddModifier adds a modifier to the personality (if it is not already present).
func (p *Personality) AddModifier(m *Modifier) {
for _, mod := range p.Modifiers {
if mod == m {
return
}
}
p.Modifiers = append(p.Modifiers, m)
p.Rebuild()
}
// RemoveModifier removes a modifier from the personality (if it is present).
func (p *Personality) RemoveModifier(m *Modifier) {
for i, mod := range p.Modifiers {
if mod == m {
p.Modifiers = append(p.Modifiers[:i], p.Modifiers[i+1:]...)
p.Rebuild()
return
}
}
}
// Get implements the Model interface and applies any modifiers to the base value.
func (p *Personality) Get(f Factor) int {
base := p.BigModel.Get(f)
if len(p.Modifiers) == 0 {
return base
}
// Apply the modifiers.
for _, m := range p.Modifiers {
base += m.Factors[f]
}
return clampTo10(base)
}
// GetFacet implements the Model interface and applies any modifiers to the base value.
func (p *Personality) GetFacet(f Facet) int {
base := p.BigModel.GetFacet(f)
if len(p.Modifiers) == 0 {
return base
}
// Apply the modifiers.
for _, m := range p.Modifiers {
base += m.Facets[f]
}
return clampTo10(base)
}
func clampTo10(val int) int {
if val > 10 {
return 10
} else if val < -10 {
return -10
}
return val
}
// Rebuild re-evaluates expressed traits based on the facet ratings.
func (p *Personality) Rebuild() {
p.Expressed = nil
for _, t := range p.t.Traits {
if t.IsExpressedBy(p) {
p.addTrait(t)
}
}
}
// Log logs the personality.
func (p *Personality) Log() {
p.BigModel.Log()
for _, t := range p.Expressed {
t.Log()
}
}
// Stats returns the stats for the personality.
func (p *Personality) Stats() *Stats {
// Rebuild the traits.
p.Rebuild()
// Calculate the stats.
s := NewStats()
for _, t := range p.Expressed {
s.add(t.Stats)
}
return s
}
// addTrait adds the given traits to the personality.
func (p *Personality) addTrait(tt ...*Trait) {
p.Expressed = mergeTraitSets(p.Expressed, tt)
}
// Interaction returns a value for how well the personalities interact face to face.
func (p *Personality) Interaction(b *Personality) int {
return Compatibility(p, b)
}
// Opinion returns the opinion of the other personality based on their reputation.
// TODO: What about a misperception of the other person?
func (p *Personality) Opinion(b *Personality) int {
var base int
// Now check if any of our traits modify the compatibility.
for _, t := range p.Expressed {
if t.Stats.Opinion[TOpinionSame] != 0 && b.hasTrait(t) {
base += t.Stats.Opinion[TOpinionSame]
} else if t.Stats.Opinion[TOpinionOpposite] != 0 && b.hasTrait(t.Opposite) {
base += t.Stats.Opinion[TOpinionOpposite]
}
}
// TODO: Add attraction opinion modifiers?
return base
}
func (p *Personality) hasTrait(t *Trait) bool {
for _, tt := range p.Expressed {
if tt == t {
return true
}
}
return false
}