LovecaSim / engine /tests /logic /test_performance_logs.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
from engine.models.ability import Effect, EffectType
class TestPerformanceLogs:
@pytest.fixture(autouse=True)
def setup(self):
self.game = GameState(verbose=True)
self.p0 = self.game.players[0]
# Pink:0, Red:1, Yellow:2, Green:3, Blue:4, Purple:5, Any:6
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, 0, 0, 0, 0, 0, 0]),
blades=1,
abilities=[],
img_path="m1.png",
)
# Red Member
self.game.member_db[2] = MemberCard(
card_id=2,
card_no="M2",
name="Member 2",
cost=1,
hearts=np.array([0, 1, 0, 0, 0, 0, 0]),
blade_hearts=np.array([0, 0, 0, 0, 0, 0, 0]),
blades=1,
abilities=[],
img_path="m2.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_requirement_reduction_log(self):
"""Verify that heart requirement reductions are logged in performance results."""
self.p0.stage[0] = 1 # Member 1 (Pink)
# We need 1 Pink and 1 Red. We have 1 Pink.
# Add a continuous effect that reduces Red requirement by 1.
self.p0.continuous_effects.append({
"source_name": "Reduction Effect",
"effect": Effect(
effect_type=EffectType.REDUCE_HEART_REQ,
value=1,
params={"color": 2} # Red is 2 in 1-6 mapping
)
})
self.p0.live_zone = [100]
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 True
# Check breakdown
assert "requirements" in res["breakdown"]
req_logs = res["breakdown"]["requirements"]
assert len(req_logs) > 0
# One of them should be our reduction
reduction_found = False
for log in req_logs:
if log["source"] == "Reduction Effect":
reduction_found = True
assert log["type"] == "req_mod"
# Value should be negative vector: Pink:0, Red:-1
assert log["value"][1] == -1
assert reduction_found
def test_performance_transform_color_log(self):
"""Verify that color transforms are logged in performance results."""
self.p0.stage[0] = 1 # Member 1 (Pink)
# We need 1 Red. We have 1 Pink.
self.game.live_db[101] = LiveCard(
card_id=101,
card_no="L2",
name="Live 2",
score=1,
required_hearts=np.array([0, 1, 0, 0, 0, 0, 0]),
abilities=[],
img_path="l2.png",
)
self.p0.live_zone = [101]
# Add a transform effect: Pink (1) -> Red (2)
self.p0.continuous_effects.append({
"source_name": "Transform Effect",
"effect": Effect(
effect_type=EffectType.TRANSFORM_COLOR,
value=0,
params={"from_color": 1, "to_color": 2}
)
})
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 True
# Check breakdown
assert "transforms" in res["breakdown"]
trans_logs = res["breakdown"]["transforms"]
assert len(trans_logs) > 0
# Check for transform log
transform_found = False
for log in trans_logs:
if log["source"] == "Transform Effect":
transform_found = True
assert log["type"] == "transform"
assert "Transform 1 Yells to 2" in log["desc"]
assert transform_found
# Also check heart_breakdown (it should still have it for legacy UI too)
heart_found = False
for log in res["breakdown"]["hearts"]:
if log.get("source") == "Transform Effect" and log.get("type") == "transform":
heart_found = True
assert heart_found
def test_performance_score_modifier_log(self):
"""Verify that ability score modifiers are logged in performance results."""
self.p0.stage[0] = 1 # Member 1 (Pink)
self.p0.live_zone = [100]
# Add a score modifier effect
from engine.models.ability import Effect, EffectType
self.p0.continuous_effects.append({
"source_name": "Score Booster",
"source_id": 999,
"effect": Effect(
effect_type=EffectType.MODIFY_SCORE_RULE,
value=5,
params={}
)
})
self.game.phase = Phase.PERFORMANCE_P1
self.game.current_player = 0
self.game._do_performance(0) # This populates results
# _do_performance calls _advance_performance -> _do_live_result
# But _do_performance itself doesn't call _do_live_result if it returns to process triggers.
# However, PhaseMixin calls _do_live_result at the end of the performance cycle.
# In this simple test, we need to ensure _do_live_result is called to populate the modifiers.
self.game._do_live_result()
# performance_results is cleared at the end of _do_live_result, but copied to last_performance_results
assert 0 in self.game.last_performance_results
res = self.game.last_performance_results[0]
assert "score_modifiers" in res["breakdown"]
mods = res["breakdown"]["score_modifiers"]
assert len(mods) > 0
found_mod = False
for m in mods:
if m["source"] == "Score Booster":
found_mod = True
assert m["value"] == 5
assert m["source_id"] == 999
assert found_mod