@@ -3,21 +3,16 @@ mod mcts;
33mod minimax;
44mod reference;
55pub use reference:: ReferenceOpponent ;
6+ // Re-export the original paths for downstream source compatibility.
7+ pub use gfa_core:: { ActionChoice , ChoiceInfo , Clock , Opponent , PlayerTurn , SearchLimits } ;
68
7- use gfa_core:: serde:: { Deserialize , Serialize } ;
89use gfa_core:: serde_json:: Value ;
910use gfa_core:: {
10- DynGame , ErrorCode , GameError , Information , LegalAction , Observation , PlayerId , SeededRng ,
11- TurnStructure , Viewer ,
11+ DynGame , ErrorCode , GameError , Information , LegalAction , PlayerId , SeededRng , TurnStructure ,
12+ Viewer ,
1213} ;
1314use std:: { sync:: Arc , time:: Instant } ;
1415
15- /// Monotonic time supplied by the host, independently of game state.
16- pub trait Clock : Send + Sync {
17- /// Milliseconds since an arbitrary fixed origin.
18- fn now_ms ( & self ) -> u64 ;
19- }
20-
2116/// System monotonic clock for interactive play.
2217pub struct SystemClock ( Instant ) ;
2318
@@ -33,102 +28,6 @@ impl Clock for SystemClock {
3328 }
3429}
3530
36- /// All information supplied to a player for one decision.
37- pub struct PlayerTurn < ' a > {
38- /// Acting seat.
39- pub seat : PlayerId ,
40- /// Seat-scoped observation; never a complete live match state.
41- pub observation : & ' a Observation ,
42- /// Canonical legal actions for this seat.
43- pub legal_actions : & ' a [ LegalAction ] ,
44- }
45-
46- /// Hard search limits. Fixed seed and node budgets reproduce decisions.
47- #[ derive( Clone , Copy , Debug ) ]
48- pub struct SearchLimits {
49- /// Maximum visited nodes, including rollout steps.
50- pub nodes : u64 ,
51- /// Maximum minimax depth and MCTS tree/rollout length.
52- pub depth : u8 ,
53- /// Wall clock time allowed, checked before each node.
54- pub time_ms : u64 ,
55- /// Independent planning RNG seed.
56- pub seed : u64 ,
57- }
58-
59- impl SearchLimits {
60- /// Provisional resource ladder. Strength calibration is reported separately.
61- pub fn for_level ( level : u8 , seed : u64 ) -> Result < Self , GameError > {
62- if !( 1 ..=10 ) . contains ( & level) {
63- return Err ( invalid ( "Level must be 1..10" ) ) ;
64- }
65- Ok ( Self {
66- nodes : 128_u64 << level,
67- depth : level,
68- time_ms : 5_000 ,
69- seed,
70- } )
71- }
72-
73- /// Reject zero or excessive resource budgets before scheduling work.
74- pub fn validate ( self ) -> Result < Self , GameError > {
75- if self . nodes == 0
76- || self . nodes > 1_000_000
77- || self . depth == 0
78- || self . depth > 64
79- || self . time_ms == 0
80- || self . time_ms > 60_000
81- {
82- return Err ( invalid (
83- "Search requires 1..1000000 nodes, 1..64 depth and 1..60000 ms" ,
84- ) ) ;
85- }
86- Ok ( self )
87- }
88- }
89-
90- /// Search diagnostics accompanying a chosen move.
91- #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
92- #[ serde( crate = "gfa_core::serde" ) ]
93- pub struct ChoiceInfo {
94- /// Optional engine-provided solving explanation.
95- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
96- pub advice : Option < gfa_core:: AdviceInfo > ,
97- /// Algorithm identifier.
98- pub algorithm : String ,
99- /// Number of visited nodes.
100- pub nodes : u64 ,
101- /// Deepest completed minimax iteration or deepest MCTS path.
102- pub depth : u8 ,
103- /// Root player's expected return, absent without completed search.
104- pub evaluation : Option < f64 > ,
105- /// Canonical principal variation, beginning with the chosen move.
106- pub principal_variation : Vec < String > ,
107- /// Whether node or time limits interrupted searching.
108- pub budget_exhausted : bool ,
109- }
110-
111- /// One legal move and optional explanatory diagnostics.
112- #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
113- #[ serde( crate = "gfa_core::serde" ) ]
114- pub struct ActionChoice {
115- /// Canonical action selected from the supplied legal list.
116- pub action : LegalAction ,
117- /// Search diagnostics.
118- pub info : ChoiceInfo ,
119- }
120-
121- /// A player that receives only its observation, legal actions and search clock.
122- pub trait Opponent : Send + Sync {
123- /// Choose one legal action without modifying the match.
124- fn choose_action (
125- & self ,
126- turn : & PlayerTurn < ' _ > ,
127- limits : SearchLimits ,
128- clock : & dyn Clock ,
129- ) -> Result < ActionChoice , GameError > ;
130- }
131-
13231/// Uniform, reproducible random baseline for any game.
13332pub struct Random ;
13433
0 commit comments