Spaces:
Running
Running
File size: 4,975 Bytes
aa9d06f |
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 |
import argparse
import json
import os
import random
import sys
# Add project root to path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import engine_rust
from ai.benchmark_decks import parse_deck
def get_action_name(action_id, game, db_json):
"""Decodes Action ID into a human-readable name."""
if action_id == 0:
return "Pass/End Phase"
phase = game.phase
p_idx = game.current_player
p_state = game.get_player(p_idx)
if phase in [-1, 0]: # Mulligan
indices = [i for i in range(len(p_state.hand)) if (action_id >> i) & 1]
return f"Mulligan: Discard indices {indices}"
if phase == 4: # Main
if 1 <= action_id <= 180:
adj = action_id - 1
hand_idx = adj // 3
slot_idx = adj % 3
if hand_idx < len(p_state.hand):
cid = p_state.hand[hand_idx]
card = db_json["member_db"].get(str(cid), {"name": f"Unknown Member {cid}"})
return f"Play {card['name']} to Slot {slot_idx}"
elif 200 <= action_id < 400:
adj = action_id - 200
slot_idx = adj // 10
ab_idx = adj % 10
return f"Activate Ability {ab_idx} in Slot {slot_idx}"
if phase == 5: # LiveSet
if 400 <= action_id < 500:
hand_idx = action_id - 400
if hand_idx < len(p_state.hand):
cid = p_state.hand[hand_idx]
card = db_json["live_db"].get(str(cid), {"name": f"Unknown Live {cid}"})
return f"Set Live: {card['name']}"
return f"Unknown Action ({action_id})"
def record_game(output_file, sims=200):
with open("data/cards_compiled.json", "r", encoding="utf-8") as f:
db_content = f.read()
db_json = json.loads(db_content)
db = engine_rust.PyCardDatabase(db_content)
game = engine_rust.PyGameState(db)
muse_deck_path = "ai/decks/muse_cup.txt"
p_deck, p_lives, p_energy = parse_deck(
muse_deck_path, db_json["member_db"], db_json["live_db"], db_json.get("energy_db", {})
)
game.initialize_game(p_deck, p_deck, p_energy, p_energy, p_lives, p_lives)
with open(output_file, "w", encoding="utf-8") as f:
f.write(f"--- GAME RECORD: MCTS ({sims} sims) vs RANDOM ---\n")
f.write(f"Deck: {muse_deck_path}\n\n")
step = 0
while not game.is_terminal() and step < 1000:
cp = game.current_player
phase = game.phase
p_state = game.get_player(cp)
phase_names = {
-1: "MulliganP1",
0: "MulliganP2",
1: "Active",
2: "Energy",
3: "Draw",
4: "Main",
5: "LiveSet",
6: "PerfP1",
7: "PerfP2",
8: "LiveResult",
}
p_name = phase_names.get(phase, f"Phase {phase}")
f.write(f"[Step {step} | Turn {game.turn} | Player {cp} ({'MCTS' if cp == 0 else 'RANDOM'}) | {p_name}]\n")
is_interactive = phase in [-1, 0, 4, 5]
if is_interactive:
tapped = sum(1 for t in p_state.tapped_energy if t)
total_en = len(p_state.energy_zone)
f.write(f" Energy: {total_en - tapped}/{total_en}\n")
f.write(f" Hand: {p_state.hand}\n")
f.write(f" Stage: {p_state.stage}\n")
f.write(f" Live Zone: {p_state.live_zone} (Revealed: {p_state.live_zone_revealed})\n")
f.write(f" Score: {p_state.score}\n")
if cp == 0:
suggestions = game.get_mcts_suggestions(sims, engine_rust.SearchHorizon.TurnEnd)
action = suggestions[0][0] if suggestions else 0
else:
legal = game.get_legal_action_ids()
action = random.choice(legal) if legal else 0
f.write(f" Action: {action} ({get_action_name(action, game, db_json)})\n")
game.step(action)
else:
game.step(0)
f.write("\n")
step += 1
f.write("\n--- GAME COMPLETE ---\n")
p0 = game.get_player(0)
p1 = game.get_player(1)
f.write(f"Final Outcome: winner={game.get_winner()}\n")
f.write(f"P0 (MCTS): Score {p0.score}, Success Lives: {len(p0.success_lives)}\n")
f.write(f"P1 (RANDOM): Score {p1.score}, Success Lives: {len(p1.success_lives)}\n")
print(f"Game record saved to {output_file}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--output", default="game_record.txt")
parser.add_argument("--sims", type=int, default=200)
args = parser.parse_args()
record_game(args.output, sims=args.sims)
|