trioskosmos commited on
Commit
c7ff874
·
verified ·
1 Parent(s): adf496b

Upload ai/verify_search_agent.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. ai/verify_search_agent.py +133 -0
ai/verify_search_agent.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+
4
+ import numpy as np
5
+
6
+ # Ensure project root is in path
7
+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
8
+
9
+ from ai.search_prob_agent import SearchProbAgent, YellOddsCalculator
10
+ from engine.game.enums import Phase as PhaseEnum
11
+ from engine.game.game_state import GameState
12
+ from engine.models.card import LiveCard, MemberCard
13
+
14
+
15
+ def test_odds_calculator():
16
+ print("Testing YellOddsCalculator...")
17
+ # Mock databases
18
+ member_db = {
19
+ 1: MemberCard(
20
+ card_id=1,
21
+ card_no="M1",
22
+ name="Red Girl",
23
+ cost=1,
24
+ hearts=np.array([1, 0, 0, 0, 0, 0, 0]),
25
+ blade_hearts=np.array([1, 0, 0, 0, 0, 0, 0]),
26
+ blades=1,
27
+ ),
28
+ 2: MemberCard(
29
+ card_id=2,
30
+ card_no="M2",
31
+ name="Blue Girl",
32
+ cost=1,
33
+ hearts=np.array([0, 0, 0, 0, 0, 1, 0]),
34
+ blade_hearts=np.array([0, 0, 0, 0, 0, 1, 0]),
35
+ blades=1,
36
+ ),
37
+ }
38
+ live_db = {
39
+ 100: LiveCard(
40
+ card_id=100, card_no="L1", name="Red Live", score=2, required_hearts=np.array([2, 0, 0, 0, 0, 0, 0])
41
+ ), # Needs 2 Red
42
+ }
43
+
44
+ calc = YellOddsCalculator(member_db, live_db)
45
+
46
+ # Situation: 1 Red on stage, 1 Red in deck, 1 Yell remaining.
47
+ stage_hearts = np.array([1, 0, 0, 0, 0, 0, 0])
48
+ deck = [1, 2, 2, 2] # 1 Red, 3 Blue
49
+
50
+ # 1 Yell: Odds should be 1/4 = 0.25
51
+ odds = calc.calculate_odds(deck, stage_hearts, [100], num_yells=1, samples=1000)
52
+ print(f"Odds with 1 yell: {odds:.3f} (Expected ~0.25)")
53
+
54
+ # 2 Yells: Odds should be higher.
55
+ # Combinations of 2 from 4: (1,B), (1,B), (1,B), (B,B), (B,B), (B,B) -> 3/6 = 0.5
56
+ odds = calc.calculate_odds(deck, stage_hearts, [100], num_yells=2, samples=1000)
57
+ print(f"Odds with 2 yells: {odds:.3f} (Expected ~0.50)")
58
+
59
+ # Needs ANY
60
+ live_db[101] = LiveCard(
61
+ card_id=101, card_no="L2", name="Any Live", score=1, required_hearts=np.array([0, 0, 0, 0, 0, 0, 2])
62
+ )
63
+ odds = calc.calculate_odds(deck, stage_hearts, [101], num_yells=1, samples=1000)
64
+ print(
65
+ f"Any Odds with 1 yell (Stage has 1, needs 2 total): {odds:.3f} (Expected ~1.0 because staging 1 counts as any if no specific color? Wait.)"
66
+ )
67
+ # Actually engine check_meet for ANY:
68
+ # staging [1,0,0,0,0,0,0] -> 1 Red.
69
+ # L101 needs 2 ANY.
70
+ # Red heart CAN be used as ANY.
71
+ # So we have 1 'available any'. We need 2.
72
+ # If Yell gives 1 Blue, we have 2 hearts total -> Successful.
73
+ # Since every card in deck has 1 heart, any yell card makes it successful.
74
+
75
+
76
+ def test_search_agent():
77
+ print("\nTesting SearchProbAgent...")
78
+ # Clear and set class-level databases (REQUIRED by game engine)
79
+ GameState.member_db = {
80
+ 1: MemberCard(
81
+ card_id=1,
82
+ card_no="M1",
83
+ name="Cheap",
84
+ cost=1,
85
+ hearts=np.array([1, 0, 0, 0, 0, 0, 0]),
86
+ blade_hearts=np.array([1, 0, 0, 0, 0, 0, 0]),
87
+ blades=1,
88
+ ),
89
+ 10: MemberCard(
90
+ card_id=10,
91
+ card_no="M10",
92
+ name="Expensive",
93
+ cost=5,
94
+ hearts=np.array([1, 1, 1, 1, 1, 1, 1]),
95
+ blade_hearts=np.array([1, 1, 1, 1, 1, 1, 1]),
96
+ blades=3,
97
+ ),
98
+ }
99
+ GameState.live_db = {
100
+ 100: LiveCard(
101
+ card_id=100, card_no="L1", name="Easy Live", score=2, required_hearts=np.array([0, 0, 0, 0, 0, 0, 1])
102
+ ),
103
+ }
104
+
105
+ state = GameState()
106
+ state.phase = PhaseEnum.MAIN
107
+ state.current_player = 0
108
+ state.players[0].hand = [1, 10]
109
+ state.players[0].energy_zone = [200, 200] # 2 energy
110
+
111
+ legal_mask = state.get_legal_actions()
112
+ legal_indices = np.where(legal_mask)[0]
113
+ print(f"Legal actions: {legal_indices}")
114
+
115
+ # Debug: Manually test step() to see if it works
116
+ print(f"\n[DEBUG] Before step: Stage = {list(state.players[0].stage)}, Hand = {state.players[0].hand}")
117
+
118
+ for action in legal_indices[:4]:
119
+ ns = state.copy()
120
+ ns = ns.step(action)
121
+ print(f" Action {action}: Stage = {list(ns.players[0].stage)}, Hand = {ns.players[0].hand}")
122
+
123
+ agent = SearchProbAgent(depth=1)
124
+ action = agent.choose_action(state, 0)
125
+ print(f"\nChosen action: {action}")
126
+ # Expected: Should play card 1 (id 1) because it can afford it (cost 1 < 2).
127
+ # Card 10 (id 10) costs 5, which is too much.
128
+ # Action 1 (index 0 in hand to slot 0) or similar.
129
+
130
+
131
+ if __name__ == "__main__":
132
+ test_odds_calculator()
133
+ test_search_agent()