@@ -17,7 +17,7 @@ impl AI {
1717 /// Returns the position (0-8) of the best move
1818 pub fn find_best_move ( & self , game : & Game ) -> Option < usize > {
1919 let available_moves = game. available_moves ( ) ;
20-
20+
2121 if available_moves. is_empty ( ) {
2222 return None ;
2323 }
@@ -40,23 +40,23 @@ impl AI {
4040 }
4141
4242 /// Minimax algorithm with depth tracking
43- ///
43+ ///
4444 /// # Arguments
4545 /// * `game` - The current game state
4646 /// * `depth` - Current depth in the game tree
4747 /// * `is_maximizing` - True if maximizing player (AI), false if minimizing (Human)
48- ///
48+ ///
4949 /// # Returns
5050 /// The score of the board state
5151 fn minimax ( & self , game : & mut Game , depth : i32 , is_maximizing : bool ) -> i32 {
5252 // Terminal state: check if game is over
5353 let score = game. evaluate ( ) ;
54-
54+
5555 // If AI won, return score minus depth (prefer faster wins)
5656 if score == 10 {
5757 return score - depth;
5858 }
59-
59+
6060 // If Human won, return score plus depth (prefer slower losses)
6161 if score == -10 {
6262 return score + depth;
@@ -71,24 +71,24 @@ impl AI {
7171 if is_maximizing {
7272 // Maximizing player (AI)
7373 let mut best_score = i32:: MIN ;
74-
74+
7575 for & position in & available_moves {
7676 let mut game_clone = self . simulate_move ( game, position, Player :: AI ) ;
7777 let score = self . minimax ( & mut game_clone, depth + 1 , false ) ;
7878 best_score = best_score. max ( score) ;
7979 }
80-
80+
8181 best_score
8282 } else {
8383 // Minimizing player (Human)
8484 let mut best_score = i32:: MAX ;
85-
85+
8686 for & position in & available_moves {
8787 let mut game_clone = self . simulate_move ( game, position, Player :: Human ) ;
8888 let score = self . minimax ( & mut game_clone, depth + 1 , true ) ;
8989 best_score = best_score. min ( score) ;
9090 }
91-
91+
9292 best_score
9393 }
9494 }
@@ -97,17 +97,17 @@ impl AI {
9797 fn simulate_move ( & self , game : & Game , position : usize , player : Player ) -> Game {
9898 // Create a copy of the current game using the board state
9999 let mut new_board = Board :: new ( ) ;
100-
100+
101101 // Copy the current board state
102102 for i in 0 ..9 {
103103 if let Some ( crate :: types:: Cell :: Occupied ( p) ) = game. board ( ) . get ( i) {
104104 new_board. make_move ( i, p) ;
105105 }
106106 }
107-
107+
108108 // Make the new move on the copied board
109109 new_board. make_move ( position, player) ;
110-
110+
111111 // Create a new game with this board state
112112 // We need to use Game::from_board or similar
113113 // For now, let's create a helper in Game
@@ -134,12 +134,12 @@ mod tests {
134134 fn test_ai_blocks_winning_move ( ) {
135135 let mut game = Game :: new ( ) ;
136136 let ai = AI :: new ( ) ;
137-
137+
138138 // Human has two in a row
139139 game. make_move ( 0 ) ; // Human X at position 0
140140 game. make_move ( 3 ) ; // AI O at position 3
141141 game. make_move ( 1 ) ; // Human X at position 1
142-
142+
143143 // AI should block position 2 to prevent human win
144144 let best_move = ai. find_best_move ( & game) ;
145145 assert_eq ! ( best_move, Some ( 2 ) ) ;
@@ -149,14 +149,14 @@ mod tests {
149149 fn test_ai_takes_winning_move ( ) {
150150 let mut game = Game :: new ( ) ;
151151 let ai = AI :: new ( ) ;
152-
152+
153153 // Setup: AI has two in a row
154154 game. make_move ( 0 ) ; // Human X
155155 game. make_move ( 3 ) ; // AI O
156156 game. make_move ( 1 ) ; // Human X
157157 game. make_move ( 4 ) ; // AI O
158158 game. make_move ( 8 ) ; // Human X
159-
159+
160160 // AI should take position 5 to win
161161 let best_move = ai. find_best_move ( & game) ;
162162 assert_eq ! ( best_move, Some ( 5 ) ) ;
@@ -166,7 +166,7 @@ mod tests {
166166 fn test_ai_finds_move_on_empty_board ( ) {
167167 let game = Game :: new ( ) ;
168168 let ai = AI :: new ( ) ;
169-
169+
170170 // AI should find a valid move
171171 let best_move = ai. find_best_move ( & game) ;
172172 assert ! ( best_move. is_some( ) ) ;
0 commit comments