LovecaSim / engine /tests /logic /test_performance_wildcard.py
trioskosmos's picture
Upload folder using huggingface_hub
bb3fbf9 verified
import numpy as np
import pytest
from engine.game.game_state import GameState, LiveCard, MemberCard
class TestPerformanceWildcard:
@pytest.fixture(autouse=True)
def setup(self):
self.game = GameState()
# Ensure clean DBs
GameState.member_db = {}
GameState.live_db = {}
self.p0 = self.game.players[0]
def test_check_hearts_exact_match(self):
"""Test specific colors match requirements exactly."""
# Need: 1 Pink (0), 1 Blue (4)
need = np.array([1, 0, 0, 0, 1, 0, 0], dtype=np.int32)
# Have: 1 Pink, 1 Blue
have = np.array([1, 0, 0, 0, 1, 0, 0], dtype=np.int32)
assert self.game._check_hearts_meet_requirement(have, need)
def test_check_hearts_insufficient_specific(self):
"""Test failure when specific colors are missing."""
need = np.array([1, 0, 0, 0, 0, 0, 0], dtype=np.int32)
have = np.array([0, 0, 0, 0, 0, 0, 0], dtype=np.int32)
assert not self.game._check_hearts_meet_requirement(have, need)
def test_check_hearts_wildcard_for_specific(self):
"""Test Wildcard (index 6) filling specific color deficit."""
# Need: 2 Pink
need = np.array([2, 0, 0, 0, 0, 0, 0], dtype=np.int32)
# Have: 0 Pink, 2 Wildcards
have = np.array([0, 0, 0, 0, 0, 0, 2], dtype=np.int32)
assert self.game._check_hearts_meet_requirement(have, need)
def test_check_hearts_wildcard_partial_specific(self):
"""Test Wildcard filling partial specific deficit."""
# Need: 3 Pink
need = np.array([3, 0, 0, 0, 0, 0, 0], dtype=np.int32)
# Have: 1 Pink, 2 Wildcards
have = np.array([1, 0, 0, 0, 0, 0, 2], dtype=np.int32)
assert self.game._check_hearts_meet_requirement(have, need)
def test_check_hearts_any_requirement_surplus(self):
"""Test Surplus specific colors filling 'Any' requirement."""
# Need: 1 Any (index 6)
need = np.array([0, 0, 0, 0, 0, 0, 1], dtype=np.int32)
# Have: 1 Pink (Surplus since 0 Pink needed)
have = np.array([1, 0, 0, 0, 0, 0, 0], dtype=np.int32)
assert self.game._check_hearts_meet_requirement(have, need)
def test_check_hearts_any_requirement_wildcard(self):
"""Test Wildcard filling 'Any' requirement."""
# Need: 1 Any
need = np.array([0, 0, 0, 0, 0, 0, 1], dtype=np.int32)
# Have: 1 Wildcard
have = np.array([0, 0, 0, 0, 0, 0, 1], dtype=np.int32)
assert self.game._check_hearts_meet_requirement(have, need)
def test_check_hearts_complex_mix(self):
"""Test simultaneous use of Wildcards for specific deficits and 'Any' requirements."""
# Need: 2 Pink, 1 Any
need = np.array([2, 0, 0, 0, 0, 0, 1], dtype=np.int32)
# Scenario A: 1 Pink, 2 Wildcards
# 1 Wildcard checks Pink deficit (1), Remaining 1 Wildcard checks Any (1) -> Pass
have_a = np.array([1, 0, 0, 0, 0, 0, 2], dtype=np.int32)
assert self.game._check_hearts_meet_requirement(have_a, need)
# Scenario B: 3 Pink, 0 Wildcards
# 2 Pink satisfy specific, 1 Pink surplus satisfies Any -> Pass
have_b = np.array([3, 0, 0, 0, 0, 0, 0], dtype=np.int32)
assert self.game._check_hearts_meet_requirement(have_b, need)
# Scenario C: 1 Pink, 1 Wildcard
# 1 Pink used. Deficit 1 Pink. 1 Wildcard used. Deficit 0.
# Any need 1. Remaining surplus/wildcard 0. -> Fail
have_c = np.array([1, 0, 0, 0, 0, 0, 1], dtype=np.int32)
assert not self.game._check_hearts_meet_requirement(have_c, need)
def test_consume_hearts_logic(self):
"""Test that _consume_hearts correctly updates the 'have' array in-place."""
# Need: 1 Pink, 1 Any
need = np.array([1, 0, 0, 0, 0, 0, 1], dtype=np.int32)
# Have: 3 Pink
have = np.array([3, 0, 0, 0, 0, 0, 0], dtype=np.int32)
# Check first
assert self.game._check_hearts_meet_requirement(have, need)
# Consume
self.game._consume_hearts(have, need)
# Expect: 1 Pink consumed for specific, 1 Pink consumed for Any. Total 2 Pink consumed.
# Remaining: 1 Pink
expected = np.array([1, 0, 0, 0, 0, 0, 0], dtype=np.int32)
np.testing.assert_array_equal(have, expected)
def test_consume_hearts_wildcard_preference(self):
"""
Verify consumption order:
1. Specific Need -> Specific Color
2. Specific Need -> Wildcard (if specific missing)
3. Any Need -> Surplus Specific
4. Any Need -> Wildcard
"""
# Need: 1 Pink, 1 Any
need = np.array([1, 0, 0, 0, 0, 0, 1], dtype=np.int32)
# Have: 0 Pink, 1 Blue (Surplus), 2 Wildcards
# 1 Wildcard needed for Pink.
# For Any: Surplus Blue available? Yes. Should use Blue or Wildcard?
# Logic says: "First consume surplus specific colors" then "consume Wildcards"
have = np.array([0, 0, 0, 0, 1, 0, 2], dtype=np.int32)
self.game._consume_hearts(have, need)
# Expect:
# Pink deficit covered by 1 Wildcard. (Wildcards: 2->1)
# Any covered by 1 Blue (Surplus). (Blue: 1->0)
# Remaining: 1 Wildcard
expected = np.array([0, 0, 0, 0, 0, 0, 1], dtype=np.int32)
np.testing.assert_array_equal(have, expected)
def test_real_data_flow(self):
"""
Integration test using real mock objects to simulate a full performance check.
Using a Member Card providing hearts and a Live Card with requirements.
"""
# Create a Mock Member: "Honoka" (Pink)
# Provides 1 Pink Heart
member = MemberCard(
card_id=101,
card_no="test",
name="Honoka",
cost=1,
hearts=np.array([1, 0, 0, 0, 0, 0, 0], dtype=np.int32), # 1 Pink
blade_hearts=np.array([0, 0, 0, 0, 0, 0, 0], dtype=np.int32),
blades=1,
)
GameState.member_db[101] = member
# Create a Mock Live: "Snow Halation"
# Require: 1 Any heart (using index 6 for test even if real card uses strict colors)
req = np.zeros(7, dtype=np.int32)
req[6] = 1 # 1 Any
live = LiveCard(card_id=201, card_no="test-live", name="Test Live", score=10, required_hearts=req)
GameState.live_db[201] = live
# Setup Player
self.p0.stage[0] = 101 # Place Honoka
self.p0.live_zone = [201] # Place Live
self.p0 = self.game.players[0]
# We need to simulate the heart gathering part of _do_performance manually
# or mock the method calls?
# Actually, let's just reuse the underlying calculation logic which is what we care about.
# 1. Gather Hearts
total_hearts = np.zeros(7, dtype=np.int32)
hraw = self.p0.get_effective_hearts(0, GameState.member_db) # Should be length 7 now [1,0,0,0,0,0,0]
total_hearts += hraw
# 2. Check Requirement
# Have: [1, 0, ...], Need: [0, ... 1 (Any)]
success = self.game._check_hearts_meet_requirement(total_hearts, live.required_hearts)
assert success, "Pink heart should satisfy 'Any' requirement in integration flow"