@@ -4,30 +4,28 @@ import dev.robothanzo.werewolf.WerewolfApplication
44import dev.robothanzo.werewolf.database.documents.Player
55import dev.robothanzo.werewolf.database.documents.Session
66import dev.robothanzo.werewolf.game.model.*
7- import dev.robothanzo.werewolf.game.roles.PredefinedRoles
87import dev.robothanzo.werewolf.game.roles.RoleRegistry
98import dev.robothanzo.werewolf.game.roles.actions.ActionExecutionResult
109import dev.robothanzo.werewolf.game.roles.actions.DeathResolutionAction
1110import dev.robothanzo.werewolf.game.roles.actions.RoleActionExecutor
1211import dev.robothanzo.werewolf.service.GameSessionService
13- import org.junit.jupiter.api.Assertions.*
12+ import org.junit.jupiter.api.Assertions.assertFalse
13+ import org.junit.jupiter.api.Assertions.assertTrue
1414import org.junit.jupiter.api.BeforeEach
1515import org.junit.jupiter.api.Test
1616import org.junit.jupiter.api.extension.ExtendWith
1717import org.mockito.Mock
18- import org.mockito.Mockito.`when`
1918import org.mockito.junit.jupiter.MockitoExtension
20- import java.util.*
2119
2220@ExtendWith(MockitoExtension ::class )
2321class DreamWeaverNightmareTest {
2422
2523 private lateinit var session: Session
2624 private lateinit var roleRegistry: RoleRegistry
27-
25+
2826 @Mock
2927 private lateinit var roleActionExecutor: RoleActionExecutor
30-
28+
3129 @Mock
3230 private lateinit var gameSessionService: GameSessionService
3331
@@ -36,26 +34,26 @@ class DreamWeaverNightmareTest {
3634 session = Session ()
3735 session.stateData = GameStateData ()
3836 session.day = 1
39-
37+
4038 // Setup static mocks
4139 WerewolfApplication .gameSessionService = gameSessionService
42-
40+
4341 // Setup Players
4442 val dw = Player (id = 1 ).apply { roles.add(" 攝夢人" ) }
4543 val nm = Player (id = 2 ).apply { roles.add(" 夢魘" ) } // Nightmare is wolf team but role logic handles it
46- nm.roles.add(" 狼人" ) // Add generic wolf role just in case or depend on Nightmare being wolf?
44+ nm.roles.add(" 狼人" ) // Add generic wolf role just in case or depend on Nightmare being wolf?
4745 // Nightmare should be a wolf role. PredefinedRoles? GameData?
4846 // In Player.isWolf, it checks: role.contains("狼") || role == "石像鬼" || role == "血月使者" || role == "惡靈騎士"
4947 // Nightmare is new. Does Player.isWolf know about it?
5048 // Player.kt: fun isWolf(role: String) { return role.contains("狼") || ... }
5149 // "夢魘" does not contain "狼". I should update Player.kt OR just add "狼人" to roles for test simplicity.
52- // Let's check Player.kt isWolf again.
50+ // Let's check Player.kt isWolf again.
5351 // It has hardcoded list. I need to update it for Nightmare too?
5452 // Or just add "狼人" as secondary role in test to make it simple.
55-
53+
5654 val villager = Player (id = 3 ).apply { roles.add(" 平民" ) }
5755 val wolf = Player (id = 4 ).apply { roles.add(" 狼人" ) }
58-
56+
5957 session.addPlayer(dw)
6058 session.addPlayer(nm)
6159 session.addPlayer(villager)
@@ -66,132 +64,155 @@ class DreamWeaverNightmareTest {
6664 fun testWolfFearBlocksCamp () {
6765 // Nightmare (ID 2) fears the Wolf (ID 4)
6866 session.stateData.nightmareFearTargets[1 ] = 4
69-
67+
7068 // This is the logic used in NightStep to filter wolves
7169 val fearedId = session.stateData.nightmareFearTargets[session.day]
7270 val isAnyWolfFeared = fearedId != null && session.getPlayer(fearedId)?.wolf == true
73-
71+
7472 assertTrue(isAnyWolfFeared, " Wolf should be detected as feared if teammate is nightmared" )
75-
73+
7674 // The list of werewolves allowed to vote should be empty in NightStep if this is true
77- val werewolves = if (isAnyWolfFeared) emptyList<Int >() else session.players.values.filter { it.wolf }.map { it.id }
75+ val werewolves =
76+ if (isAnyWolfFeared) emptyList<Int >() else session.players.values.filter { it.wolf }.map { it.id }
7877 assertTrue(werewolves.isEmpty(), " Werewolf voting list should be empty if a wolf is nightmared" )
7978 }
8079
8180 @Test
8281 fun testDreamWeaverImmunity () {
8382 // Day 1: Dream Weaver links Villager
8483 session.stateData.dreamWeaverTargets[1 ] = 3
85-
84+
8685 // Wolf kills Villager
8786 val executionResult = ActionExecutionResult ()
8887 executionResult.deaths.getOrPut(DeathCause .WEREWOLF ) { mutableListOf () }.add(3 )
89-
88+
9089 // Run Death Resolution
9190 val resolutionAction = DeathResolutionAction ()
92- val result = resolutionAction.execute(session, RoleActionInstance (0 , " " , null , mutableListOf (), ActionSubmissionSource .SYSTEM , ActionStatus .PROCESSED ), executionResult)
93-
91+ val result = resolutionAction.execute(
92+ session,
93+ RoleActionInstance (0 , " " , null , mutableListOf (), ActionSubmissionSource .SYSTEM , ActionStatus .PROCESSED ),
94+ executionResult
95+ )
96+
9497 // Villager should NOT be in deaths (Immunity)
95- assertFalse(result.deaths[DeathCause .WEREWOLF ]?.contains(3 ) == true , " Villager should be immune to Wolf kill due to Dream Weaver" )
98+ assertFalse(
99+ result.deaths[DeathCause .WEREWOLF ]?.contains(3 ) == true ,
100+ " Villager should be immune to Wolf kill due to Dream Weaver"
101+ )
96102 }
97103
98104 @Test
99105 fun testDreamWeaverConsecutiveDeath () {
100106 // Day 1: Dream Weaver links Villager (done in history)
101107 session.stateData.dreamWeaverTargets[1 ] = 3
102-
108+
103109 // Day 2
104110 session.day = 2
105111 // Dream Weaver links Villager AGAIN
106112 session.stateData.dreamWeaverTargets[2 ] = 3
107-
113+
108114 val executionResult = ActionExecutionResult ()
109-
115+
110116 // Run Death Resolution
111117 val resolutionAction = DeathResolutionAction ()
112- val result = resolutionAction.execute(session, RoleActionInstance (0 , " " , null , mutableListOf (), ActionSubmissionSource .SYSTEM , ActionStatus .PROCESSED ), executionResult)
113-
118+ val result = resolutionAction.execute(
119+ session,
120+ RoleActionInstance (0 , " " , null , mutableListOf (), ActionSubmissionSource .SYSTEM , ActionStatus .PROCESSED ),
121+ executionResult
122+ )
123+
114124 // Villager should die from Dream Weaver
115- assertTrue(result.deaths[DeathCause .DREAM_WEAVER ]?.contains(3 ) == true , " Villager should die due to consecutive Dream Weaver link" )
125+ assertTrue(
126+ result.deaths[DeathCause .DREAM_WEAVER ]?.contains(3 ) == true ,
127+ " Villager should die due to consecutive Dream Weaver link"
128+ )
116129 }
117130
118131 @Test
119132 fun testDreamWeaverLinkedDeath () {
120133 // Day 1: Dream Weaver links Villager
121134 session.stateData.dreamWeaverTargets[1 ] = 3
122-
135+
123136 // Dream Weaver dies (e.g. Wolf kill)
124137 val executionResult = ActionExecutionResult ()
125138 executionResult.deaths.getOrPut(DeathCause .WEREWOLF ) { mutableListOf () }.add(1 ) // 1 is DW
126-
139+
127140 // Run Death Resolution
128141 val resolutionAction = DeathResolutionAction ()
129- val result = resolutionAction.execute(session, RoleActionInstance (0 , " " , null , mutableListOf (), ActionSubmissionSource .SYSTEM , ActionStatus .PROCESSED ), executionResult)
130-
142+ val result = resolutionAction.execute(
143+ session,
144+ RoleActionInstance (0 , " " , null , mutableListOf (), ActionSubmissionSource .SYSTEM , ActionStatus .PROCESSED ),
145+ executionResult
146+ )
147+
131148 // Dream Weaver dies
132149 assertTrue(result.deaths[DeathCause .WEREWOLF ]?.contains(1 ) == true )
133150 // Villager should also die (Linked Death)
134- assertTrue(result.deaths[DeathCause .DREAM_WEAVER ]?.contains(3 ) == true , " Villager should die because Dream Weaver died" )
151+ assertTrue(
152+ result.deaths[DeathCause .DREAM_WEAVER ]?.contains(3 ) == true ,
153+ " Villager should die because Dream Weaver died"
154+ )
135155 }
136156
137157 @Test
138158 fun testNightmareFearRestriction () {
139159 // Day 1 night: Nightmare fears Villager (ID 3)
140160 session.stateData.nightmareFearTargets[1 ] = 3
141161 session.currentState = " NIGHT_PHASE"
142-
162+
143163 // Villager tries to use skill? (e.g. if Villager was Seer)
144164 // Here we test SessionExtensions.isActionAvailable manually or mock logic
145165 // But since I modified SessionExtensions, I can test the logic directly if I can invoke extension method.
146166 // Assuming test can call extension method:
147-
167+
148168 // Let's pretend Villager is Seer for this test
149169 val seer = Player (id = 5 ).apply { roles.add(" 預言家" ) }
150170 session.addPlayer(seer)
151-
171+
152172 // Fear Seer
153173 session.stateData.nightmareFearTargets[1 ] = 5
154-
174+
155175 // Create a dummy Seer Action
156- val actionId = ActionDefinitionId .SEER_CHECK
157-
176+ ActionDefinitionId .SEER_CHECK
177+
158178 // To test isActionAvailable, we need RoleRegistry mock
159179 // Instead of full registry, let's just inspect the logic we added:
160180 // if (fearedId == playerId && isNightPhase) return false
161-
162- // I will reproduce the logic here to verify my understanding/implementation or use reflection if needed,
181+
182+ // I will reproduce the logic here to verify my understanding/implementation or use reflection if needed,
163183 // but ideally I should call the actual method.
164- // Since I cannot easily compile extensions in this test snippet without full context setup,
184+ // Since I cannot easily compile extensions in this test snippet without full context setup,
165185 // I will trust the logic `if (fearedId == playerId && isNightPhase) return false` which is simple.
166-
186+
167187 // Instead, let's test Werewolf Kill restriction
168188 // Nightmare fears Wolf (ID 4)
169189 session.stateData.nightmareFearTargets[1 ] = 4
170-
190+
171191 // Helper to simulate Wolf Kill execution
172192 val killActionInstance = RoleActionInstance (
173- actor = 4 ,
174- actorRole = " WEREWOLF" ,
193+ actor = 4 ,
194+ actorRole = " WEREWOLF" ,
175195 actionDefinitionId = ActionDefinitionId .WEREWOLF_KILL ,
176196 targets = mutableListOf (3 ), // Try to kill Villager
177197 submittedBy = ActionSubmissionSource .PLAYER ,
178198 status = ActionStatus .SUBMITTED
179199 )
180-
200+
181201 // Use a real WerewolfKillAction (or anonymous subclass if needed)
182202 // I need to instantiate WerewolfKillAction. Since it's a class, I can just new it.
183203 val wolfKillAction = dev.robothanzo.werewolf.game.roles.actions.WerewolfKillAction ()
184-
204+
185205 val executionResult = ActionExecutionResult ()
186-
206+
187207 val result = wolfKillAction.execute(session, killActionInstance, executionResult)
188-
208+
189209 // Result should NOT have death because wolf teammate is feared
190210 assertFalse(result.deaths.containsKey(DeathCause .WEREWOLF ), " Wolf kill should fail if teammate is feared" )
191-
211+
192212 // Verify log is added (mock session addLog?)
193213 // assert(session.logs.isNotEmpty()) // Mocking logs might be hard with just data class
194214 }
215+
195216 @Test
196217 fun testNightmareActionIsCompulsory () {
197218 val action = dev.robothanzo.werewolf.game.roles.actions.NightmareFearAction ()
0 commit comments