@@ -42,7 +42,7 @@ fn mid_map(
4242 decay_countdown_value : usize ,
4343 cached_decay_interval_value : isize ,
4444 is_decaying_value : bool ,
45- ) -> PyResult < Py < Board > > {
45+ ) -> PyResult < Py < GameSearchTree > > {
4646 let a_direction = Action :: new ( a_direction) ;
4747 let b_direction = Action :: new ( b_direction) ;
4848
@@ -69,7 +69,8 @@ fn mid_map(
6969 is_decaying_value,
7070 ) ;
7171
72- Python :: with_gil ( |py| Py :: new ( py, board) )
72+ let tree = GameSearchTree :: new ( & board) ;
73+ Python :: with_gil ( |py| Py :: new ( py, tree) )
7374}
7475
7576#[ pyfunction]
@@ -84,101 +85,11 @@ fn board_eq(a: Board, b: Board) -> bool {
8485 a == b
8586}
8687
87- fn naive_minmax_search (
88- state : & mut Board ,
89- depth : usize ,
90- alpha : f32 ,
91- beta : f32 ,
92- rng : & mut impl Rng ,
93- ) -> f32 {
94- if state. get_valid_moves ( ) . amount ( ) == 0 {
95- // Terminal state
96- return if state. is_player_a { -1.0 } else { 1.0 } ;
97- } else if depth <= 0 {
98- // Calculate and return heuristic
99- return state. get_naive_heuristic ( ) ;
100- }
101- if state. is_player_a {
102- let mut value = f32:: MIN ;
103- let mut my_alpha = alpha;
104-
105- for action in state. get_valid_moves ( ) . actions_randomized ( rng) {
106- state. step_in ( action, |state| {
107- value = f32:: max (
108- value,
109- naive_minmax_search ( state, depth - 1 , my_alpha, beta, rng) ,
110- ) ;
111- } ) ;
112- if value > beta {
113- break ;
114- }
115- my_alpha = f32:: max ( my_alpha, value) ;
116- }
117- value
118- } else {
119- let mut value = f32:: MAX ;
120- let mut my_beta = beta;
121-
122- for action in state. get_valid_moves ( ) . actions_randomized ( rng) {
123- state. step_in ( action, |state| {
124- value = f32:: min (
125- value,
126- naive_minmax_search ( state, depth - 1 , alpha, my_beta, rng) ,
127- ) ;
128- } ) ;
129-
130- if value < alpha {
131- break ;
132- }
133- my_beta = f32:: min ( my_beta, value) ;
134- }
135- value
136- }
137- }
138-
139- #[ pyfunction]
140- fn get_best_action ( state : & mut Board ) -> u8 {
141- let mut best_action = Action :: FF ;
142- let mut best_value = if state. is_player_a {
143- f32:: MIN
144- } else {
145- f32:: MAX
146- } ;
147- let mut rng = rand:: rngs:: SmallRng :: from_os_rng ( ) ;
148-
149- for action in state. get_valid_moves ( ) . actions_randomized ( & mut rng) {
150- let value = state. step_in ( action, |state| {
151- naive_minmax_search ( state, 12 , f32:: MIN , f32:: MAX , & mut rng)
152- } ) ;
153-
154- if state. is_player_a {
155- if value > best_value {
156- best_value = value;
157- best_action = action;
158- }
159- } else {
160- if value < best_value {
161- best_value = value;
162- best_action = action;
163- }
164- }
165- }
166- best_action as u8
167- }
168-
169- #[ pyfunction]
170- fn create_search_tree ( state : & mut Board ) -> PyResult < Py < GameSearchTree > > {
171- let tree = GameSearchTree :: new ( state) ;
172- Python :: with_gil ( |py| Py :: new ( py, tree) )
173- }
174-
17588/// A Python module implemented in Rust.
17689#[ pymodule]
17790fn alpha_snake ( m : & Bound < ' _ , PyModule > ) -> PyResult < ( ) > {
17891 m. add_function ( wrap_pyfunction ! ( mid_map, m) ?) ?;
17992 m. add_function ( wrap_pyfunction ! ( board_eq, m) ?) ?;
180- m. add_function ( wrap_pyfunction ! ( get_best_action, m) ?) ?;
181- m. add_function ( wrap_pyfunction ! ( create_search_tree, m) ?) . unwrap ( ) ;
18293 Ok ( ( ) )
18394}
18495
0 commit comments