Spaces:
Running
Running
File size: 6,482 Bytes
ae55ffb |
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 os
import time
import engine_rust
def run_battle():
# Load DB
db_path = "data/cards_compiled.json"
if not os.path.exists(db_path):
print(f"Error: {db_path} not found")
return
with open(db_path, "r", encoding="utf-8") as f:
db_json = f.read()
db = engine_rust.PyCardDatabase(db_json)
# Models
models = {
"Original (New)": "original",
"Simple (Old)": "simple",
}
# Battle setup
contestants = list(models.keys())
results = {c: {"wins": 0, "games": 0} for c in contestants}
# Deck setup (Standard starter)
lives0 = [30000, 30001, 30002]
deck0 = [
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
] + lives0
deck1 = deck0.copy()
lives1 = lives0.copy()
print(f"{'Battle':<20} | {'Winner':<20} | {'Duration'}")
print("-" * 60)
# Round robin (partial for speed, can adjust)
for i in range(len(contestants)):
for j in range(i + 1, len(contestants)):
p0_name = contestants[i]
p1_name = contestants[j]
p0_agent = models[p0_name]
p1_agent = models[p1_name]
# Run 1 game
start = time.time()
game = engine_rust.PyGameState(db)
game.initialize_game(deck0, deck1, [], [], lives0, lives1)
step_count = 0
while not game.is_terminal() and step_count < 1000:
curr_p = game.current_player
phase = game.phase
turn = game.turn
agent_name = p0_name if curr_p == 0 else p1_name
agent = p0_agent if curr_p == 0 else p1_agent
print(f"\n{'=' * 40}")
print(f"Step {step_count} | Turn {turn} | Player {curr_p} ({agent_name}) | Phase {phase}")
# Show Legal Actions
legal_ids = game.get_legal_action_ids()
print(f" Legal Actions ({len(legal_ids)}): {legal_ids}")
if phase in [-1, 0]:
sel = game.get_player(curr_p).mulligan_selection
print(f" Mulligan Selection Mask: {sel:016b}")
if isinstance(agent, engine_rust.PyHybridMCTS):
stats = agent.get_suggestions(game, 0, 0.5)
else:
stats = game.search_mcts(0, 0.5, agent)
# Show Top 5
stats.sort(key=lambda x: x[2], reverse=True)
print(" Top Actions (MCTS Visits/Score):")
for act, score, visits in stats[:5]:
print(f" - Action {act:<4}: Score {score:.4f}, Visits {visits}")
# Trace Best Path (Next 3 steps)
if stats and step_count % 10 == 0:
print(" Predicted Best Path (Simulated):")
try:
# Attempt to use copy() or fallback to manual property copy
if hasattr(game, "copy"):
temp_game = game.copy()
else:
temp_game = engine_rust.PyGameState(db)
temp_game.current_player = game.current_player
temp_game.first_player = game.first_player
temp_game.phase = game.phase
temp_game.turn = game.turn
temp_game.set_player(0, game.get_player(0))
temp_game.set_player(1, game.get_player(1))
path_str = []
trace_curr = temp_game
for depth in range(3):
p = trace_curr.current_player
ph = trace_curr.phase
t = trace_curr.turn
# For the first step, use the MCTS top action
if depth == 0:
best_act = stats[0][0]
else:
# Quick MCTS search for lookahead (100 sims)
t_stats = trace_curr.search_mcts(100, 0.0, "original")
if not t_stats:
break
t_stats.sort(key=lambda x: x[2], reverse=True)
best_act = t_stats[0][0]
path_str.append(f"[T{t} P{p} Ph{ph} Act{best_act}]")
trace_curr.step(best_act)
if trace_curr.is_terminal():
break
print(f" {' -> '.join(path_str)}")
except Exception as e:
print(f" (Path trace failed: {e})")
action = stats[0][0] if stats else 0
game.step(action)
step_count += 1
# Check for progress
if step_count % 10 == 0:
p0 = game.get_player(0)
p1 = game.get_player(1)
print(
f"--- P0: Lives {len(p0.success_lives)}, Hand {len(p0.hand)} | P1: Lives {len(p1.success_lives)}, Hand {len(p1.hand)}"
)
winner_idx = game.get_winner()
winner_name = "Draw"
if winner_idx == 0:
winner_name = p0_name
results[p0_name]["wins"] += 1
elif winner_idx == 1:
winner_name = p1_name
results[p1_name]["wins"] += 1
results[p0_name]["games"] += 1
results[p1_name]["games"] += 1
elapsed = time.time() - start
print(f"{p0_name} vs {p1_name:<10} | {winner_name:<20} | {elapsed:.1f}s")
print("\nFinal Scoreboard:")
for name, stats in results.items():
wr = (stats["wins"] / stats["games"] * 100) if stats["games"] > 0 else 0
print(f"{name:<20}: {stats['wins']}/{stats['games']} ({wr:.1f}% Win Rate)")
if __name__ == "__main__":
run_battle()
|