File size: 2,107 Bytes
78738de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3
"""Sanity + baseline PositionPlayEnv (stage 2a): agent random đánh N cú.

Chạy từ gốc repo:
    python examples/random_agent_position.py 300

Mong đợi (design doc §7): env chạy không lỗi; pot ~2-4%, contact ~17-18%,
scratch ~20-22% (tương tự stage 1 vì reward gốc giữ nguyên); Q|pot là baseline
mới cần ghi lại để so với PPO.
"""

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))

import numpy as np

from poolcoach_rl.envs import PositionPlayEnv


def main(n_episodes: int = 300):
    env = PositionPlayEnv(seed=42)
    rewards, aims, qs_on_pot = [], [], []
    potted = scratched = contacted = b2_potted = makeable = 0

    for _ in range(n_episodes):
        env.reset()
        action = env.action_space.sample()
        _, reward, terminated, truncated, info = env.step(action)
        assert terminated and not truncated
        rewards.append(reward)
        potted += info["potted"]
        scratched += info["scratch"]
        contacted += info["contact"]
        b2_potted += info["b2_potted"]
        aims.append(info["aim_cos"])
        if info["potted"] and not info["scratch"]:
            qs_on_pot.append(info["pos_q"])
            makeable += info["pos_q"] > 0.5

    n_pot = len(qs_on_pot)
    print(f"Episodes      : {n_episodes}")
    print(f"Pot rate      : {potted / n_episodes:.1%}")
    print(f"Contact rate  : {contacted / n_episodes:.1%}")
    print(f"Scratch rate  : {scratched / n_episodes:.1%}")
    print(f"B2 lucky pot  : {b2_potted / n_episodes:.1%}")
    print(f"Q | pot       : {np.mean(qs_on_pot):.3f} (n={n_pot})"
          if n_pot else "Q | pot       : n/a (0 cú pot)")
    print(f"Makeable Q>.5 : {makeable / n_pot:.1%}" if n_pot
          else "Makeable Q>.5 : n/a")
    print(f"Aim cos mean  : {np.mean(aims):+.4f}")
    print(f"Reward mean   : {np.mean(rewards):+.4f}")
    print(f"Reward min/max: {np.min(rewards):+.4f} / {np.max(rewards):+.4f}")


if __name__ == "__main__":
    n = int(sys.argv[1]) if len(sys.argv) > 1 else 300
    main(n)