Spaces:
Sleeping
Sleeping
File size: 3,163 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 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 | #!/usr/bin/env python3
"""
Demo pooltool cho PoolCoach — minh hoạ những hook cần cho RL position play.
Cài đặt (máy local, nên dùng Python 3.10-3.12):
pip install pooltool-billiards
Chạy headless (không GUI):
python pooltool_demo.py
Bật GUI 3D xem cú đánh (cần màn hình; ESC để thoát):
python pooltool_demo.py --gui
"""
import sys
import pooltool as pt
def build_nineball_shot():
"""Dựng một hệ 9-ball chuẩn + một cú đánh có spin."""
table = pt.Table.default()
balls = pt.get_rack(pt.GameType.NINEBALL, table) # rack 9-ball đúng luật
cue = pt.Cue(cue_ball_id="cue")
shot = pt.System(table=table, balls=balls, cue=cue)
# === ĐÂY LÀ "ACTION" CỦA AGENT ===
# V0 = lực, phi = góc hướng, a = english (side spin), b = draw/follow
shot.cue.set_state(
V0=8.0, # power
phi=pt.aim.at_ball(shot, "1"), # angle: nhắm bi số 1 (luật 9-ball: bi nhỏ nhất trước)
a=0.0, # spin_x: english trái/phải
b=0.2, # spin_y: follow (dương) / draw (âm) -> điều bi cái
)
return shot
def observation(shot):
"""OBSERVATION cho RL: toạ độ (x, y) của mọi bi còn trên bàn."""
obs = {}
for ball_id, ball in shot.balls.items():
xyz = ball.state.rvw[0] # vị trí [x, y, z]
obs[ball_id] = (round(float(xyz[0]), 4), round(float(xyz[1]), 4))
return obs
def summarize_events(shot):
"""REWARD source: đọc events sau cú đánh."""
pocketed, cushions, ball_hits = [], 0, 0
for e in shot.events:
etype = str(e.event_type)
if "pocket" in etype.lower():
pocketed.append([a.id for a in e.agents])
elif "cushion" in etype.lower():
cushions += 1
elif etype.lower().endswith("ball_ball"):
ball_hits += 1
return pocketed, cushions, ball_hits
def main():
shot = build_nineball_shot()
print("== Vị trí bi TRƯỚC cú đánh ==")
for bid, xy in observation(shot).items():
print(f" {bid:>4}: {xy}")
# === "STEP": mô phỏng headless, rất nhanh nhờ event-based + Numba ===
pt.simulate(shot, inplace=True)
print(f"\nSố sự kiện mô phỏng: {len(shot.events)}")
print(f"Thời gian mô phỏng (giây): {shot.t:.3f}")
pocketed, cushions, ball_hits = summarize_events(shot)
print("\n== Tín hiệu cho REWARD ==")
print(f" Bi vào lỗ: {pocketed if pocketed else 'không'}")
print(f" Số lần chạm băng: {cushions}")
print(f" Số va chạm bi-bi: {ball_hits}")
print("\n== Vị trí bi SAU cú đánh (đặc biệt xem 'cue' -> position play) ==")
for bid, xy in observation(shot).items():
print(f" {bid:>4}: {xy}")
# GUI 3D: KHÔNG simulate lại (shot đã simulate ở trên — hệ hết năng
# lượng, simulate nữa là rỗng); pt.show tự continuize theo fps.
if "--gui" in sys.argv:
pt.show(shot, title="PoolCoach demo — break 9-ball")
if __name__ == "__main__":
main()
|