13.1 The Limits of Optimal Strategy
13.1.1 Why Perfect Play Is Impossible
Before presenting strategies, I must acknowledge fundamental limitations:
Human Unpredictability:
- Emotional decisions override rational analysis
- Personal relationships affect voting regardless of evidence
- Fatigue, stress, and group dynamics create irrational outcomes
- Players may have hidden agendas (entertainment, relationships)
- Private conversations are unobservable
- Internal emotional states are hidden
- Strategic intentions cannot be perfectly inferred
- New information arrives continuously
Social Detection:
- Optimal play often looks optimal
- Visibly strategic behaviour attracts suspicion
- "Playing the game" is itself evidence against you
- Natural behaviour is valued over calculated behaviour
Game Theory Limitations:
- Not all players are rational actors
- Mixed strategy equilibria are unplayable in practice
- Reputation effects span beyond single games (for celebrities)
- Production editing affects future player knowledge
13.1.2 The Value of Strategic Thinking
Despite these limitations, strategic frameworks provide:
- Decision Scaffolding: Principles to guide choices under pressure
- Pattern Recognition: Understanding what behaviours indicate
- Risk Assessment: Evaluating tradeoffs systematically
- Adaptability: Recognising when to deviate from default approaches
Go Implementation: Strategy Configuration:
// StrategyConfig represents adjustable strategy parameters
type StrategyConfig struct {
RiskTolerance float64 // [0,1] willingness to take risks
SocialPriority float64 // [0,1] weighting of relationships vs analysis
Adaptability float64 // [0,1] willingness to change approach
Visibility float64 // [0,1] preference for visible vs hidden play
EndgameFocus float64 // [0,1] sacrifice early position for late advantage
}
// OptimalConfig returns balanced strategy parameters
func OptimalConfig() *StrategyConfig {
return &StrategyConfig{
RiskTolerance: 0.4, // Moderate risk-taking
SocialPriority: 0.5, // Balance social and analytical
Adaptability: 0.7, // High adaptability
Visibility: 0.4, // Slightly prefer hidden play
EndgameFocus: 0.6, // Weight toward endgame survival
}
}
13.2 Faithful Strategy
13.2.1 Core Objective
Win Condition: Eliminate all Traitors before Traitors equal or outnumber Faithfuls.
Strategic Imperatives (for analysis of different player types, see Strategic Archetypes):
- Survive (cannot win if banished or murdered)
- Identify Traitors (primary contribution)
- Build alliance with other Faithfuls (voting power)
- Avoid false accusations (wastes banishments)
- Protect other analytical Faithfuls (collective intelligence)
13.2.2 Early Game Strategy (Days 1-3)
Primary Focus: Information gathering and relationship building
Recommended Approach:
FAITHFUL EARLY GAME ALGORITHM:
1. OBSERVE: Establish behavioural baselines for all players
2. CONNECT: Form 2-3 genuine relationships (potential allies)
3. AVOID: Strong accusations without evidence
4. DOCUMENT: Mental or physical notes on observations
5. POSITION: Central social location without leadership claims
Specific Tactics:
| Tactic | Rationale | Risk |
|---|---|---|
| Participate in all group activities | Creates observation opportunities | Medium (visibility) |
| Ask open-ended questions | Generates behavioural data | Low |
| Share minor observations | Builds credibility without commitment | Low |
| Avoid strong alliances yet | Maintains flexibility | Medium (isolation) |
| Express uncertainty | Appears thoughtful, not paranoid | Low |
Go Implementation: Early Game Decision:
// EarlyGameDecision determines Faithful behaviour in Days 1-3
type EarlyGameDecision struct {
Phase GamePhase
PlayerState *PlayerState
GameState *GameState
}
type EarlyGameAction int
const (
ActionObserve EarlyGameAction = iota
ActionConnect
ActionShareObservation
ActionAskQuestion
ActionParticipate
)
func (d *EarlyGameDecision) SelectAction() EarlyGameAction {
day := d.GameState.DayNumber
suspicionOnSelf := d.calculateSuspicionOnSelf()
allianceCount := len(d.PlayerState.Alliances)
// Priority: build relationships first
if allianceCount < 2 && day <= 2 {
return ActionConnect
}
// If under suspicion, contribute visibly
if suspicionOnSelf > 0.4 {
return ActionShareObservation
}
// Default: gather information
if rand.Float64() < 0.6 {
return ActionObserve
}
return ActionParticipate
}
func (d *EarlyGameDecision) calculateSuspicionOnSelf() float64 {
totalSuspicion := 0.0
count := 0
for _, player := range d.GameState.Players {
if !player.IsAlive || player.ID == d.PlayerState.ID {
continue
}
totalSuspicion += player.Emotion.SuspicionMap[d.PlayerState.ID]
count++
}
if count == 0 {
return 0.0
}
return totalSuspicion / float64(count)
}
13.2.3 Mid Game Strategy (Days 4-8)
Primary Focus: Pattern analysis and coalition building
Key Observations to Track:
- Murder Patterns (utilising memory systems to track history):
- Who survives despite being visible targets?
- Are alliance leaders being systematically eliminated?
- Is anyone "untouchable"?
- Vote Patterns:
- Who has never voted for a revealed Traitor?
- Who consistently votes with suspected Traitors?
- Whose votes seem strategically coordinated?
- Behavioural Shifts:
- Who changed after Traitor selections?
- Who defends accused players unusually strongly?
- Who pivots suspicion when pressure mounts?
Mid Game Algorithm:
FAITHFUL MID GAME ALGORITHM:
1. ANALYSE: Compile murder and vote patterns
2. COALITION: Form voting bloc with trusted allies
3. TARGET: Identify highest-confidence Traitor suspect
4. COORDINATE: Ensure coalition votes together
5. VERIFY: After banishment, update model based on reveal
6. ITERATE: Refine suspicions and repeat
Go Implementation: Pattern Analysis:
// PatternAnalysis tracks suspicious patterns for Faithful decision-making
type PatternAnalysis struct {
PlayerID PlayerID
MurderSurvivors map[PlayerID]int // Count of survival despite targeting
VoteHistory map[PlayerID][]Vote
TraitorVotes map[PlayerID]int // Votes for revealed Traitors
FaithfulVotes map[PlayerID]int // Votes for revealed Faithfuls
}
// CalculateSuspicionScore returns composite suspicion based on patterns
func (pa *PatternAnalysis) CalculateSuspicionScore(target PlayerID) float64 {
score := 0.0
// Survival pattern: survived many rounds without apparent risk
survivalScore := float64(pa.MurderSurvivors[target]) * 0.1
score += math.Min(survivalScore, 0.3)
// Vote pattern: ratio of Faithful votes to Traitor votes
traitorVotes := pa.TraitorVotes[target]
faithfulVotes := pa.FaithfulVotes[target]
totalVotes := traitorVotes + faithfulVotes
if totalVotes > 0 {
// Higher ratio of votes for Faithfuls = more suspicious
faithfulRatio := float64(faithfulVotes) / float64(totalVotes)
score += faithfulRatio * 0.4
}
// Never voted for a Traitor is suspicious
if traitorVotes == 0 && totalVotes >= 3 {
score += 0.2
}
return math.Min(score, 1.0)
}
// GetTopSuspects returns players ranked by suspicion
func (pa *PatternAnalysis) GetTopSuspects(n int) []PlayerID {
type suspect struct {
ID PlayerID
Score float64
}
var suspects []suspect
for pid := range pa.MurderSurvivors {
suspects = append(suspects, suspect{
ID: pid,
Score: pa.CalculateSuspicionScore(pid),
})
}
sort.Slice(suspects, func(i, j int) bool {
return suspects[i].Score > suspects[j].Score
})
result := make([]PlayerID, 0, n)
for i := 0; i < n && i < len(suspects); i++ {
result = append(result, suspects[i].ID)
}
return result
}
13.2.4 Late Game Strategy (Days 9+)
Primary Focus: Final Traitor elimination and endgame decision
Critical Calculations:
| Remaining | Traitors Possible | Risk Level | Strategy |
|---|---|---|---|
| 6 players | 1-2 | Medium | Target highest suspicion |
| 5 players | 1-2 | High | Must eliminate correctly |
| 4 players | 1 | Critical | One wrong vote = Traitor win |
| 3 players | 1 | Maximum | Must identify or end correctly |
| 2 players | 0-1 | Final | Automatic outcome |
Late Game Algorithm:
FAITHFUL LATE GAME ALGORITHM:
1. COUNT: Calculate maximum remaining Traitors
2. ASSESS: Evaluate conviction level for each survivor
3. DECIDE: Vote only if confidence exceeds threshold
4. END CHECK: If believe all Traitors gone, vote to end
5. CONTINUE: If uncertain, vote to continue (one more banishment)
End Game Decision Framework:
// EndgameDecision represents the final "End or Continue" choice
type EndgameDecision struct {
Player *PlayerState
Survivors []*PlayerState
TraitorsBanished int
InitialTraitors int
ConfidenceMap map[PlayerID]float64 // Confidence each survivor is Faithful
}
type EndgameChoice int
const (
ChoiceEnd EndgameChoice = iota
ChoiceContinue
)
// Decide returns whether to end or continue the game
func (ed *EndgameDecision) Decide() EndgameChoice {
// Calculate expected remaining Traitors
maxTraitorsRemaining := ed.InitialTraitors - ed.TraitorsBanished
if maxTraitorsRemaining <= 0 {
// All Traitors should be gone
return ChoiceEnd
}
// Calculate confidence all survivors are Faithful
allFaithfulConfidence := 1.0
for _, survivor := range ed.Survivors {
if survivor.ID == ed.Player.ID {
continue // Know own role
}
faithfulConfidence := 1.0 - ed.Player.Emotion.SuspicionMap[survivor.ID]
allFaithfulConfidence *= faithfulConfidence
}
// If confident all survivors are Faithful, end
if allFaithfulConfidence > 0.7 {
return ChoiceEnd
}
// If uncertain and more than 2 survivors, continue
if len(ed.Survivors) > 2 {
return ChoiceContinue
}
// Final 2: must make a call
// Higher confidence = end, lower = impossible to continue anyway
if allFaithfulConfidence > 0.5 {
return ChoiceEnd
}
return ChoiceContinue
}
13.2.5 Defensive Tactics When Accused
When Under Suspicion:
- Remain Calm: Defensive anger validates suspicion
- Address Specifics: Counter each point with evidence
- Redirect Logically: Offer alternative explanations without wild accusations
- Use Alliance: Let trusted allies defend you
- Accept Uncertainty: "I understand why you might think that, but..."
What NOT to Do:
- Attack the accuser's credibility aggressively
- Make counter-accusations without evidence
- Become silent and withdrawn
- Over-explain beyond what's asked
- Reference information you shouldn't have
13.3 Traitor Strategy
13.3.1 Core Objective
Win Condition: At least one Traitor survives to final (when Traitors equal or outnumber Faithfuls, or game ends).
Strategic Imperatives:
- Survive banishment (primary)
- Eliminate Faithfuls through murder (reduce opposition)
- Misdirect Faithful investigations (protect fellow Traitors)
- Build trust with key Faithfuls (manipulation access)
- Manage fellow Traitors (coordination without exposure)
13.3.2 Early Game Strategy (Days 1-3)
Primary Focus: Establish credibility and identify targets
Recommended Approach:
TRAITOR EARLY GAME ALGORITHM:
1. BEHAVE: Act exactly as you would as a Faithful
2. CONNECT: Build genuine-seeming relationships
3. IDENTIFY: Note which Faithfuls are analytical threats
4. COORDINATE: Align murder targets with fellow Traitors
5. AVOID: Premature accusations or defenses of fellow Traitors
Murder Target Selection (Early):
| Target Type | Priority | Rationale |
|---|---|---|
| Detective archetype | High | Will eventually identify you |
| Alliance leader | Medium-High | Disrupts Faithful coordination |
| Random/no pattern | Varies | Prevents pattern analysis |
| Shielded player | Avoid | Wastes murder opportunity |
| Isolated player | Low | Less impactful, may raise questions |
Go Implementation: Murder Target Selection:
// MurderTargetSelector helps Traitors choose optimal murder targets
type MurderTargetSelector struct {
GameState *GameState
TraitorState *PlayerState
FellowTraitors []PlayerID
}
type TargetScore struct {
Player PlayerID
ThreatScore float64
SafetyScore float64 // Risk of selection causing suspicion
TotalScore float64
}
// EvaluateTargets scores all possible murder targets
func (mts *MurderTargetSelector) EvaluateTargets() []TargetScore {
var scores []TargetScore
for _, player := range mts.GameState.Players {
if !player.IsAlive || player.Role != Faithful {
continue
}
// Skip shielded players
if mts.GameState.ActiveShields[player.ID] {
continue
}
score := mts.evaluateTarget(player)
scores = append(scores, score)
}
// Sort by total score descending
sort.Slice(scores, func(i, j int) bool {
return scores[i].TotalScore > scores[j].TotalScore
})
return scores
}
func (mts *MurderTargetSelector) evaluateTarget(target *PlayerState) TargetScore {
score := TargetScore{Player: target.ID}
// Threat score: how dangerous is this Faithful?
threatScore := 0.0
// Analytical players are threats
if target.CurrentStrategy == StrategyDetective {
threatScore += 0.4
}
// Players suspicious of Traitors are threats
for _, traitorID := range mts.FellowTraitors {
threatScore += target.Emotion.SuspicionMap[traitorID] * 0.3
}
// Alliance leaders are threats (coordinate against Traitors)
if len(target.Alliances) >= 2 {
threatScore += 0.2
}
score.ThreatScore = math.Min(threatScore, 1.0)
// Safety score: how safe is killing this target?
safetyScore := 0.5 // Baseline
// Killing close allies of Traitors looks suspicious
for _, traitorID := range mts.FellowTraitors {
traitor := mts.GameState.Players[traitorID]
if rel, ok := traitor.Relationships[target.ID]; ok {
safetyScore -= rel.Closeness * 0.2
}
}
// Killing isolated players is safer (fewer people investigating)
if len(target.Alliances) == 0 {
safetyScore += 0.15
}
score.SafetyScore = math.Max(0, math.Min(safetyScore, 1.0))
// Total: weight threat more than safety
score.TotalScore = score.ThreatScore*0.65 + score.SafetyScore*0.35
return score
}
13.3.3 Mid Game Strategy (Days 4-8)
Primary Focus: Survival and misdirection
Key Tactics:
- Vote Pattern Management:
- Vote for fellow Traitor if they're definitely being banished (creates credibility)
- Avoid always voting together with fellow Traitors
- Occasionally vote for Faithfuls who will survive (appears to be wrong, like everyone else)
- Misdirection:
- Subtly cast doubt on analytical Faithfuls
- Support multiple competing theories (divides Faithful attention)
- Appear to be actively hunting Traitors
- The Hero Play (Advanced):
- Lead accusation against struggling fellow Traitor
- Gain massive credibility as "Traitor hunter"
- Use credibility to protect remaining Traitors
Hero Play Decision Matrix:
// HeroPlayDecision evaluates whether to sacrifice a fellow Traitor
type HeroPlayDecision struct {
Player *PlayerState
Target *PlayerState // Fellow Traitor to potentially sacrifice
TargetSuspicion float64 // How suspicious is the target?
OwnSuspicion float64 // How suspicious am I?
TraitorsRemaining int
}
type HeroPlayChoice int
const (
HeroPlayAvoid HeroPlayChoice = iota
HeroPlaySubtle // Quietly vote against, don't lead
HeroPlayFull // Lead the accusation
)
func (hpd *HeroPlayDecision) Evaluate() HeroPlayChoice {
// Never sacrifice if only 2 Traitors remain (need numbers)
if hpd.TraitorsRemaining <= 2 {
return HeroPlayAvoid
}
// Don't sacrifice if target might survive
if hpd.TargetSuspicion < 0.6 {
return HeroPlayAvoid
}
// If target is definitely doomed (>0.8 suspicion), might as well benefit
if hpd.TargetSuspicion > 0.8 {
// Full hero play if I need credibility
if hpd.OwnSuspicion > 0.4 {
return HeroPlayFull
}
// Subtle if I'm safe (don't need the spotlight)
return HeroPlaySubtle
}
// Medium suspicion on target: consider if I desperately need credibility
if hpd.OwnSuspicion > 0.6 {
return HeroPlayFull
}
return HeroPlayAvoid
}
// CredibilityGain calculates credibility boost from successful hero play
func (hpd *HeroPlayDecision) CredibilityGain(choice HeroPlayChoice) float64 {
switch choice {
case HeroPlayFull:
return 0.4 // Major credibility boost
case HeroPlaySubtle:
return 0.15 // Minor credibility boost
default:
return 0.0
}
}
13.3.4 Late Game Strategy (Days 9+)
Primary Focus: Final survival and prize maximisation
Critical Thresholds:
| Situation | Strategy |
|---|---|
| Multiple Traitors, safe | Maintain coordination, spread targets |
| Multiple Traitors, one exposed | Consider sacrifice for survivor |
| Solo Traitor, unsuspected | Lay low, vote with consensus |
| Solo Traitor, suspected | Aggressive misdirection, find scapegoat |
Endgame Decision:
// TraitorEndgameDecision handles final game decisions
type TraitorEndgameDecision struct {
Player *PlayerState
FellowTraitors []*PlayerState
Faithfuls []*PlayerState
TotalSurvivors int
}
func (ted *TraitorEndgameDecision) ShouldVoteEnd() bool {
traitorCount := len(ted.FellowTraitors) + 1 // Include self
faithfulCount := len(ted.Faithfuls)
// If Traitors >= Faithfuls, definitely end (we win)
if traitorCount >= faithfulCount {
return true
}
// If continuing risks exposing fellow Traitor, consider ending
// (Better to share prize than lose everything)
if traitorCount > 1 {
for _, traitor := range ted.FellowTraitors {
if ted.isSuspectedBy(traitor, ted.Faithfuls) {
// Fellow Traitor is in danger
// If we end now, at least some of us survive
if traitorCount >= faithfulCount-1 {
return true // End before they catch us
}
}
}
}
// Generally, don't end if Traitors < Faithfuls
return false
}
func (ted *TraitorEndgameDecision) isSuspectedBy(traitor *PlayerState, faithfuls []*PlayerState) bool {
highSuspicionCount := 0
for _, faithful := range faithfuls {
if faithful.Emotion.SuspicionMap[traitor.ID] > 0.6 {
highSuspicionCount++
}
}
return highSuspicionCount >= len(faithfuls)/2
}
13.4 Recruited Traitor Strategy
Recruited Traitors represent a fascinating strategic position, explored in depth in the Puppet Master Hypothesis and the Secret Traitor analysis.
13.4.1 The Transition Challenge
Recruited Traitors face unique difficulties:
- Behavioural Discontinuity: Sudden role change may be detectable
- Loyalty Conflict: Former Faithful allies become targets
- Knowledge Gap: Less experience than Original Traitors
- Trust Deficit: Original Traitors may view recruit as liability
- Guilt Burden: Emotional weight of betraying former allies (see Emotion and Deception Engine)
13.4.2 Post-Recruitment Immediate Actions
First 24 Hours After Recruitment:
RECRUITED TRAITOR IMMEDIATE ALGORITHM:
1. STABILISE: Control emotional display (guilt, fear, excitement)
2. MAINTAIN: Continue previous behavioural patterns exactly
3. COORDINATE: Learn Traitor protocols from fellow Traitors
4. ASSESS: Identify which former allies are most suspicious
5. PLAN: Develop strategy for managing former relationships
Go Implementation: Recruitment Transition:
// RecruitmentTransition manages the Faithful-to-Traitor shift
type RecruitmentTransition struct {
Player *PlayerState
FormerAllies []*PlayerState
NewAllies []*PlayerState // Fellow Traitors
TransitionDay int
EmotionalStrain float64
}
// GetBehaviouralGuidelines returns post-recruitment behaviour guidance
func (rt *RecruitmentTransition) GetBehaviouralGuidelines() []string {
guidelines := []string{
"Maintain exact same relationship behaviour with former allies",
"Do not suddenly become quiet or withdrawn",
"Do not suddenly become overly active or helpful",
"Continue voicing suspicions as before (but steer away from Traitors)",
"Allow yourself to appear uncertain (you always were)",
}
// Add specific guidance based on former allies
for _, ally := range rt.FormerAllies {
guidelines = append(guidelines,
fmt.Sprintf("Continue confiding in %s but share only safe information", ally.Name))
}
return guidelines
}
// CalculateExposureRisk assesses risk of detection from transition
func (rt *RecruitmentTransition) CalculateExposureRisk() float64 {
baseRisk := 0.2 // All recruits have baseline detection risk
// Risk increases with number of close former allies
allyRisk := float64(len(rt.FormerAllies)) * 0.08
baseRisk += math.Min(allyRisk, 0.3)
// Risk increases with emotional strain (produces tells)
strainRisk := rt.EmotionalStrain * 0.25
baseRisk += strainRisk
// Risk increases over time (more opportunities to slip)
daysSinceRecruitment := rt.Player.GameState.DayNumber - rt.TransitionDay
timeRisk := float64(daysSinceRecruitment) * 0.03
baseRisk += math.Min(timeRisk, 0.2)
return math.Min(baseRisk, 1.0)
}
13.4.3 Managing Former Alliances
The Core Dilemma: Your closest allies are now your biggest threats (they know your baseline best).
Strategies:
| Former Relationship | Recommended Approach |
|---|---|
| Very close ally | Gradually distance through "disagreements" |
| Medium ally | Maintain but share less information |
| Casual acquaintance | Continue as before |
| Suspected you pre-recruitment | Extreme caution; they may notice changes |
Murder Target Considerations for Recruits:
- Former close allies may need elimination (they'll notice changes)
- BUT killing close ally immediately looks suspicious
- Best approach: Wait 2-3 days, then target former ally when plausible narrative exists
13.5 Endgame Optimisation: Seeding Final Contestants
13.5.1 The Endgame Selection Problem
The final contestants determine the outcome. Strategic players should work to shape who reaches the finale.
Ideal Endgame Compositions:
For Traitors:
| Composition | Outcome | Notes |
|---|---|---|
| 2T, 1F | Traitor victory | Perfect setup |
| 1T, 1F | Traitor victory | Works if game ends here |
| 1T, 2F | Risky | Must survive one more banishment |
For Faithfuls:
| Composition | Outcome | Notes |
|---|---|---|
| 3F, 0T | Faithful victory | Ideal (must correctly identify) |
| 2F, 0T | Faithful victory | Must vote to end correctly |
| 2F, 1T | Risky | Must identify correctly or lose |
13.5.2 Seeding Strategy for Traitors
Goal: Reach endgame with Traitor(s) and trusting Faithfuls.
Phase-by-Phase Seeding:
// TraitorSeedingStrategy plans for optimal endgame composition
type TraitorSeedingStrategy struct {
CurrentDay int
RemainingDays int
Traitors []*PlayerState
Faithfuls []*PlayerState
}
type SeedingAction struct {
ActionType string
Target PlayerID
Rationale string
Priority float64
}
// GetSeedingActions returns prioritised actions to shape endgame
func (tss *TraitorSeedingStrategy) GetSeedingActions() []SeedingAction {
var actions []SeedingAction
// Identify Faithfuls by trust level
trustingFaithfuls := tss.getTrustingFaithfuls()
suspiciousFaithfuls := tss.getSuspiciousFaithfuls()
// Priority 1: Eliminate analytical Faithfuls who will figure things out
for _, f := range suspiciousFaithfuls {
if tss.isAnalytical(f) {
actions = append(actions, SeedingAction{
ActionType: "murder",
Target: f.ID,
Rationale: "Remove analytical threat before they expose Traitors",
Priority: 0.9,
})
}
}
// Priority 2: Preserve trusting Faithfuls for endgame
for _, f := range trustingFaithfuls {
actions = append(actions, SeedingAction{
ActionType: "protect",
Target: f.ID,
Rationale: "Trusting Faithful will vote to end game when prompted",
Priority: 0.7,
})
}
// Priority 3: Eliminate alliance leaders (disrupts Faithful coordination)
for _, f := range tss.Faithfuls {
if len(f.Alliances) >= 2 {
actions = append(actions, SeedingAction{
ActionType: "murder",
Target: f.ID,
Rationale: "Remove alliance coordinator",
Priority: 0.6,
})
}
}
// Sort by priority
sort.Slice(actions, func(i, j int) bool {
return actions[i].Priority > actions[j].Priority
})
return actions
}
func (tss *TraitorSeedingStrategy) getTrustingFaithfuls() []*PlayerState {
var trusting []*PlayerState
for _, f := range tss.Faithfuls {
avgTraitorSuspicion := 0.0
for _, t := range tss.Traitors {
avgTraitorSuspicion += f.Emotion.SuspicionMap[t.ID]
}
avgTraitorSuspicion /= float64(len(tss.Traitors))
if avgTraitorSuspicion < 0.3 {
trusting = append(trusting, f)
}
}
return trusting
}
func (tss *TraitorSeedingStrategy) getSuspiciousFaithfuls() []*PlayerState {
var suspicious []*PlayerState
for _, f := range tss.Faithfuls {
for _, t := range tss.Traitors {
if f.Emotion.SuspicionMap[t.ID] > 0.5 {
suspicious = append(suspicious, f)
break
}
}
}
return suspicious
}
13.5.3 Prize Optimisation: Share vs Take All
The Final Decision:
When game reaches conclusion, Traitors must decide:
- Take All: Traitors split entire prize among themselves
- Share: Requires Faithfuls to believe no Traitors remain (vote to end)
Mathematical Framework:
// PrizeOptimisation calculates optimal endgame for Traitor
type PrizeOptimisation struct {
TotalPrize float64
TraitorCount int
FaithfulCount int
DetectionRisk float64 // Probability of being caught if game continues
}
// ExpectedValue calculates expected prize for different strategies
func (po *PrizeOptimisation) ExpectedValue(strategy string) float64 {
switch strategy {
case "take_all":
// If Traitors >= Faithfuls, win immediately
if po.TraitorCount >= po.FaithfulCount {
return po.TotalPrize / float64(po.TraitorCount)
}
// Otherwise, must survive more rounds
survivalProb := 1.0 - po.DetectionRisk
expectedShare := po.TotalPrize / float64(po.TraitorCount)
return expectedShare * survivalProb
case "share_attempt":
// Must convince Faithfuls game is over
// Probability they believe = 1 - (their average suspicion of Traitors)
successProb := 0.5 // Simplified; would need actual suspicion data
if successProb > 0 {
sharedPrize := po.TotalPrize / float64(po.TraitorCount+po.FaithfulCount)
return sharedPrize * successProb
}
return 0.0
case "end_now":
// Vote to end and reveal
if po.TraitorCount >= po.FaithfulCount {
return po.TotalPrize / float64(po.TraitorCount)
}
return 0.0 // Faithfuls win
default:
return 0.0
}
}
// OptimalStrategy returns the best approach
func (po *PrizeOptimisation) OptimalStrategy() string {
takeAll := po.ExpectedValue("take_all")
share := po.ExpectedValue("share_attempt")
endNow := po.ExpectedValue("end_now")
if takeAll >= share && takeAll >= endNow {
return "take_all"
}
if share >= endNow {
return "share_attempt"
}
return "end_now"
}
13.6 Conclusion: Theory vs Practice
13.6.1 Summary of Key Strategies
Faithful Optimal Play:
- Observe systematically, document patterns
- Build coalitions but maintain flexibility
- Target highest-confidence suspects only
- Know when to end (confidence > 70%)
Traitor Optimal Play:
- Behave authentically as a Faithful would
- Eliminate analytical threats through murder
- Build trust to gain manipulation access
- Consider hero plays when beneficial
- Seed endgame with trusting Faithfuls
Recruited Traitor Optimal Play:
- Maintain behavioural consistency immediately
- Gradually distance from closest former allies
- Contribute to Traitor coordination without overreaching
- Accept emotional burden; channel into motivation
13.6.2 The Human Element
These strategies assume rational actors optimising for victory. Reality includes:
- Players who prioritise entertainment over winning
- Genuine friendships that override strategy
- Emotional decisions in high-pressure moments
- Fatigue and stress-induced errors
- Production manipulation of circumstances
The best strategy is ultimately adaptability: recognising when these frameworks apply and when human dynamics require different approaches. For insights into how audiences perceive these strategic choices, and how different international versions reward different playstyles, see the respective chapters.