LovecaSim / engine /tests /logic /test_performance_results.py
trioskosmos's picture
Upload folder using huggingface_hub
bb3fbf9 verified
import numpy as np
import pytest
from engine.game.enums import Phase
from engine.game.game_state import GameState, LiveCard, MemberCard
class TestPerformanceResults:
@pytest.fixture(autouse=True)
def setup(self):
self.game = GameState(verbose=True)
self.p0 = self.game.players[0]
# Setup mock databases
self.game.member_db[1] = MemberCard(
card_id=1,
card_no="M1",
name="Member 1",
cost=1,
hearts=np.array([1, 0, 0, 0, 0, 0, 0]),
blade_hearts=np.array([0, 1, 0, 0, 0, 0, 0]),
blades=1,
abilities=[],
img_path="m1.png",
)
self.game.live_db[100] = LiveCard(
card_id=100,
card_no="L1",
name="Live 1",
score=1,
required_hearts=np.array([1, 1, 0, 0, 0, 0, 0]),
abilities=[],
img_path="l1.png",
)
def test_performance_results_population(self):
"""Verify that _do_performance populates performance_results correctly."""
# 1. Setup Stage & Live Zone
self.p0.stage[0] = 1 # Member 1 in Area 0
self.p0.live_zone = [100] # Live 1 in Live Zone
# 2. Setup Yell Card (Member 1 also used as yell)
# This will provide 1 Red Blade Heart.
# Member 1 in stage provides 1 Pink Heart.
# Total: 1 Pink, 1 Red. Requirement for Live 1: 1 Pink, 1 Red.
self.p0.main_deck = [1]
# 3. Trigger Performance Phase 1
self.game.phase = Phase.PERFORMANCE_P1
self.game.current_player = 0
# Manually call _do_performance
self.game._do_performance(0)
# 4. Verify results
assert 0 in self.game.performance_results
res = self.game.performance_results[0]
assert res["success"] is True
assert len(res["member_contributions"]) == 1
assert res["member_contributions"][0]["id"] == 1
# Expect 7 elements for hearts (6 colors + Any/Star)
assert res["member_contributions"][0]["hearts"] == [1, 0, 0, 0, 0, 0, 0]
assert len(res["yell_cards"]) == 1
assert res["yell_cards"][0]["id"] == 1
assert res["yell_cards"][0]["blade_hearts"] == [0, 1, 0, 0, 0, 0, 0]
# Total hearts should be [1, 1, 0, 0, 0, 0, 0] (Pink, Red, ...)
assert res["total_hearts"] == [1, 1, 0, 0, 0, 0, 0]
assert len(res["lives"]) == 1
assert res["lives"][0]["id"] == 100
assert res["lives"][0]["passed"] == True
assert res["lives"][0]["score"] == 1
def test_performance_results_cleared_on_reset(self):
"""Verify that performance_results are cleared on game reset."""
self.game.performance_results[0] = {"dummy": "data"}
self.game._reset()
assert not self.game.performance_results
def test_mixed_performance_results(self):
"""Verify that multiple lives track individual pass/fail status and scoring correctly."""
# Setup: Live 1 (ID 100) needs Pink+Red. Live 2 (ID 101) needs 2 Pink.
self.game.live_db[101] = LiveCard(
card_id=101,
card_no="L2",
name="Live 2",
score=2,
required_hearts=np.array([2, 0, 0, 0, 0, 0, 0]),
abilities=[],
img_path="l2.png",
)
# Player has 1 Pink (Member 1) and 1 Red (Yell).
# Live 1 (index 0) needs 1 Pink, 1 Red -> PASSED.
# Live 2 (index 1) needs 2 Pink -> FAILED (only 0 Pink remain after consumption).
self.p0.stage[0] = 1 # Member 1
self.p0.live_zone = [100, 101]
self.p0.main_deck = [1] # For yell
self.game.phase = Phase.PERFORMANCE_P1
self.game.current_player = 0
self.game._do_performance(0)
res = self.game.performance_results[0]
assert res["success"] is False # Overall success is false because not all met
assert len(res["lives"]) == 2
# Live 1 should be passed
assert res["lives"][0]["id"] == 100
assert res["lives"][0]["passed"] is True
# Live 2 should be failed
assert res["lives"][1]["id"] == 101
assert res["lives"][1]["passed"] is False
# Score calculation in LiveResult phase
self.game.phase = Phase.LIVE_RESULT
self.game._do_live_result()
# Rule 8.4.7: Because Live 2 failed, the entire performance failed (Rule 8.3.16).
# Score should be 0.
assert self.p0.score == 0
def test_tie_penalty(self):
"""Verify Rule 8.4.7.1: Tie with 2+ cards results in 0 points."""
# Setup: P0 and P1 both perform 2 lives successfully.
p0, p1 = self.game.players[0], self.game.players[1]
self.game.live_db[102] = LiveCard(
card_id=102, card_no="L3", name="L3", score=1, required_hearts=np.array([0] * 7), abilities=[], img_path=""
)
self.game.live_db[103] = LiveCard(
card_id=103, card_no="L4", name="L4", score=1, required_hearts=np.array([0] * 7), abilities=[], img_path=""
)
p0.passed_lives = [100, 102]
p1.passed_lives = [101, 103]
# Scoring: Both have 2 points (Live 1 + Live 3 vs Live 2 + Live 4)
# Note: I'm manually Setting passed_lives to skip _do_performance heart checks
self.game.phase = Phase.LIVE_RESULT
self.game._do_live_result()
# Both tied with 2+ cards -> should get 0 points
assert p0.score == 0
assert p1.score == 0
assert len(p0.success_lives) == 0
assert len(p1.success_lives) == 0
def test_interactive_selection_choice(self):
"""Verify Rule 8.4.7.3: Multiple successful lives create a SELECT_SUCCESS_LIVE choice."""
# Setup: P0 performs 2 lives, P1 performs 0.
p0 = self.game.players[0]
self.game.live_db[102] = LiveCard(
card_id=102, card_no="L3", name="L3", score=1, required_hearts=np.array([0] * 7), abilities=[], img_path=""
)
p0.passed_lives = [100, 102]
self.game.players[1].passed_lives = []
self.game.phase = Phase.LIVE_RESULT
self.game._do_live_result()
# P0 wins but has 2 cards -> choice pending
assert len(self.game.pending_choices) == 1
assert self.game.pending_choices[0][0] == "SELECT_SUCCESS_LIVE"
assert self.game.pending_choices[0][1]["player_id"] == 0
assert self.game.pending_choices[0][1]["cards"] == [100, 102]
assert self.game.current_player == 0