# 🔍 Truth Path Audit - Hearthside Secrets

**Date**: Implementation Review  
**Purpose**: Verify variant system integrity from start to reveal

---

## ✅ Issue 1: RevealSolution & DetermineWinners - FIXED

### **Problem**
```lua
// OLD - Used scenario.solution
self.scenario.solution
culprit = self.scenario.solution.culprit
```

### **Fix Applied**
```lua
// NEW - Uses variant.solution
self.variant.solution
solution.actors (array of actors)
```

**Status**: ✅ Complete

---

## ✅ Issue 2: Player Count Alignment - FIXED

### **Problem**
- README.md said 4-8 players
- Scenario file said 4-8 players
- Design target was 5-10 players

### **Fix Applied**
- `missing_brew.lua`: Updated to `min = 5, max = 10`
- `README.md`: Updated to "5-10 players (including host)"

**Status**: ✅ Complete

---

## ⚠️ Issue 3: Role Names vs Player Names - CRITICAL

### **Problem Identified**

**Current accusation flow**:
```lua
accusation.targetPlayer = "The Thief"  // Role name?
solution.actors = {"The Thief"}        // Role name!
```

**But players have actual names**:
```lua
gameController.players = {
  ["Playername-Realm"] = {
    role = { name = "The Thief" }
  }
}
```

### **The Mismatch**

When players submit accusations, they need to accuse:
- **Option A**: A role ("I accuse The Thief")
- **Option B**: A player ("I accuse Playername-Realm")

Currently, the system compares `accusation.targetPlayer` to `solution.actors`, which contains **role names** like "The Thief".

But `targetPlayer` suggests it should be a **player name**.

### **Required Decision**

**If accusations target ROLES**:
```lua
// Players accuse roles
accusation.targetPlayer = "The Thief"  // Actually a role name
solution.actors = {"The Thief"}

// Check
if accusation.targetPlayer == actor then  // Works!
```

**If accusations target PLAYERS**:
```lua
// Players accuse actual people
accusation.targetPlayer = "Playername-Realm"
solution.actors = {"The Thief"}  // Role names

// Need to resolve player → role
local playerData = gameController.players[accusation.targetPlayer]
local playerRole = playerData.role.name

// Then check
if playerRole == actor then  // Works!
```

### **Recommendation**

**Use Option B (Player Names)** because:
1. More intuitive for social deduction
2. Players know each other by character name
3. Matches real-world "I accuse Bob" gameplay
4. Prevents meta-gaming role names

### **Required Changes**

1. **AccusationManager.lua**:
```lua
function AccusationManager:IsAccusationCorrect(gameController, accusation)
  local solution = gameController.variant.solution
  
  -- Get accused player's role
  local playerData = gameController.players[accusation.targetPlayer]
  if not playerData then
    return false
  end
  
  local accusedRole = playerData.role.name
  
  -- Check if role matches solution actors
  for _, actor in ipairs(solution.actors) do
    if accusedRole == actor then
      return true
    end
  end
  
  return false
end
```

2. **GameController.lua DetermineWinners**:
```lua
function GameController:DetermineWinners()
  local solution = self.variant.solution
  local winners = {}
  
  for _, accusation in ipairs(self.accusations) do
    -- Get accused player's role
    local playerData = self.players[accusation.targetPlayer]
    if playerData then
      local accusedRole = playerData.role.name
      
      -- Check if role matches solution actors
      for _, actor in ipairs(solution.actors) do
        if accusedRole == actor then
          table.insert(winners, accusation.accuser)
          break
        end
      end
    end
  end
  
  return winners
end
```

**Status**: ⚠️ **NEEDS FIX**

---

## 🔄 Issue 4: Variant-Specific Location Clues

### **Current State**

Location clues are defined at scenario level:
```lua
locations = {
  {
    id = "tavern",
    clues = {
      { text = "Wet spot near cellar door", type = "PUBLIC" }
    }
  }
}
```

These are **shared across all variants**.

### **Problem**

Players can meta-game by remembering location clues:
- "Last time, the wet spot meant the thief used the cellar"
- "The cart tracks always mean courtyard theft"

### **Solution**

Move location clues into variants:
```lua
variants = {
  theft = {
    locationClues = {
      tavern = {
        { text = "Wet spot near cellar door", type = "PUBLIC" }
      },
      courtyard = {
        { text = "Cart tracks in mud", type = "PUBLIC" }
      }
    },
    roles = { ... },
    solution = { ... }
  },
  
  coverup = {
    locationClues = {
      tavern = {
        { text = "Smell of smoke from kitchen", type = "PUBLIC" }
      },
      kitchen = {
        { text = "Keg hidden behind hearth", type = "PUBLIC" }
      }
    },
    roles = { ... },
    solution = { ... }
  }
}
```

### **Implementation**

1. Move clues from `scenario.locations` to `variant.locationClues`
2. Update `LocationManager:InitializeLocations()` to merge variant clues
3. Keep base location structure at scenario level

**Status**: 📋 **PLANNED**

---

## 🎯 Full Truth Path

### **Game Start**
1. ✅ `GameController:StartGame(scenarioId)`
2. ✅ Loads scenario from `HS.Data.Scenarios[scenarioId]`
3. ✅ Calls `SelectRandomVariant(scenario)`
4. ✅ Stores in `self.variant`

### **Role Assignment**
5. ✅ `RoleManager:AssignRoles(gameController, playerList)`
6. ✅ Gets roles from `variant.roles`
7. ✅ Assigns to `gameController.players[playerName]`
8. ✅ Updates ParticipantRoster with role names

### **Clue Distribution**
9. ✅ `RoleManager:GetInitialClues(role)` - Gets role clues
10. ⚠️ `LocationManager:InitializeLocations()` - Uses scenario clues (should use variant)

### **Accusation**
11. ⚠️ `SubmitAccusation(targetPlayer, ...)` - Needs clarification: role or player?
12. ⚠️ `AccusationManager:IsAccusationCorrect()` - Currently checks role names
13. ⚠️ Should resolve player name → role name first

### **Reveal**
14. ✅ `RevealSolution()` - Uses `variant.solution`
15. ✅ Broadcasts `variant.solution` to all players

### **Winners**
16. ⚠️ `DetermineWinners()` - Checks `solution.actors` (role names)
17. ⚠️ Compares to `accusation.targetPlayer` (player name?)
18. ⚠️ **MISMATCH** - Needs player → role resolution

---

## 🚨 Critical Fixes Required

### **Priority 1: Role/Player Name Resolution**
- Fix `AccusationManager:IsAccusationCorrect()`
- Fix `GameController:DetermineWinners()`
- Add player name → role name lookup

### **Priority 2: Variant Location Clues**
- Move location clues into variants
- Update LocationManager to use variant clues
- Ensure replayability

### **Priority 3: Network Sync**
- Verify variant selection syncs to participants
- Ensure solution reveal uses variant data
- Check accusation messages use correct names

---

## 📝 Testing Checklist

### **Variant Selection**
- [ ] Game starts with scenario ID
- [ ] Random variant selected
- [ ] Variant logged (debug only)
- [ ] Variant stored in gameController

### **Role Assignment**
- [ ] Roles come from variant
- [ ] Players receive correct roles
- [ ] Role names stored in player data

### **Accusations**
- [ ] Players accuse by player name
- [ ] System resolves player → role
- [ ] Comparison checks role vs solution.actors

### **Reveal**
- [ ] Solution from variant shown
- [ ] Winners determined correctly
- [ ] Multiple actors supported (coverup variant)

### **Replayability**
- [ ] Different variant each game
- [ ] Different clues per variant
- [ ] No meta-gaming possible

---

## 🎯 Summary

**Fixed**:
- ✅ RevealSolution uses variant.solution
- ✅ DetermineWinners uses variant.solution
- ✅ Player counts aligned (5-10)

**Needs Fix**:
- ⚠️ Role name vs player name in accusations
- ⚠️ Player → role resolution in winner determination
- 📋 Variant-specific location clues

**Next Action**: Fix accusation system to properly resolve player names to roles before checking against solution.actors.
