Spaces:
Running
Running
File size: 7,431 Bytes
bb3fbf9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
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"
|