|  |  |  | @ -3,6 +3,7 @@ use std::{fmt, mem}; | 
			
		
	
		
			
				
					|  |  |  |  | use std::fmt::{Display, Formatter, Write}; | 
			
		
	
		
			
				
					|  |  |  |  | use rand::{Rng, rngs::OsRng}; | 
			
		
	
		
			
				
					|  |  |  |  | use std::borrow::Borrow; | 
			
		
	
		
			
				
					|  |  |  |  | use permutator::copy::k_permutation; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug,Clone)] | 
			
		
	
		
			
				
					|  |  |  |  | struct Board([Bin; 24]); | 
			
		
	
	
		
			
				
					|  |  |  | @ -176,7 +177,7 @@ struct Player { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug, Clone)] | 
			
		
	
		
			
				
					|  |  |  |  | pub struct State { | 
			
		
	
		
			
				
					|  |  |  |  |     move_number : usize, | 
			
		
	
		
			
				
					|  |  |  |  |     turn_number: usize, | 
			
		
	
		
			
				
					|  |  |  |  |     turn : Color, | 
			
		
	
		
			
				
					|  |  |  |  |     board: Board, | 
			
		
	
		
			
				
					|  |  |  |  |     roll: Roll, | 
			
		
	
	
		
			
				
					|  |  |  | @ -186,9 +187,9 @@ pub struct State { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug,Clone,Copy)] | 
			
		
	
		
			
				
					|  |  |  |  | pub enum Move { | 
			
		
	
		
			
				
					|  |  |  |  |     InBoard(u8, u8), | 
			
		
	
		
			
				
					|  |  |  |  |     Enter(u8), | 
			
		
	
		
			
				
					|  |  |  |  |     BearOff(u8) | 
			
		
	
		
			
				
					|  |  |  |  |     InBoard(/* from */ u8, /* to */ u8), | 
			
		
	
		
			
				
					|  |  |  |  |     Enter(/* pos */ u8), | 
			
		
	
		
			
				
					|  |  |  |  |     BearOff(/* pos */ u8) | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug)] | 
			
		
	
	
		
			
				
					|  |  |  | @ -283,7 +284,7 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn start(turn : Option<Color>) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         // The state is laid out for the white player
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut state = State { | 
			
		
	
		
			
				
					|  |  |  |  |             move_number: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             turn_number: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             turn: Color::White, | 
			
		
	
		
			
				
					|  |  |  |  |             board: Board([ | 
			
		
	
		
			
				
					|  |  |  |  |                 // 1 .. 12 (bottom row, right to left)
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -325,10 +326,14 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |         state | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Get turn info. Returns a tuple of `(turn_number, turn_color)`, where
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// `turn_number` is incremented after each turn ends (can be used to detect
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// automatic turn skips that result in the same player playing again.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn turn(&self) -> (usize, Color) { | 
			
		
	
		
			
				
					|  |  |  |  |         (self.move_number, self.turn) | 
			
		
	
		
			
				
					|  |  |  |  |         (self.turn_number, self.turn) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Get reference to own player struct
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn player(&self) -> &Player { | 
			
		
	
		
			
				
					|  |  |  |  |         match self.turn { | 
			
		
	
		
			
				
					|  |  |  |  |             Color::Black => &self.black, | 
			
		
	
	
		
			
				
					|  |  |  | @ -336,6 +341,7 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Get mutable reference to own player struct
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn player_mut(&mut self) -> &mut Player { | 
			
		
	
		
			
				
					|  |  |  |  |         match self.turn { | 
			
		
	
		
			
				
					|  |  |  |  |             Color::Black => &mut self.black, | 
			
		
	
	
		
			
				
					|  |  |  | @ -343,6 +349,7 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Get reference to the other player's struct
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn other(&self) -> &Player { | 
			
		
	
		
			
				
					|  |  |  |  |         match self.turn { | 
			
		
	
		
			
				
					|  |  |  |  |             Color::Black => &self.white, | 
			
		
	
	
		
			
				
					|  |  |  | @ -350,6 +357,7 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Get mutable reference to the other player's struct
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn other_mut(&mut self) -> &mut Player { | 
			
		
	
		
			
				
					|  |  |  |  |         match self.turn { | 
			
		
	
		
			
				
					|  |  |  |  |             Color::Black => &mut self.white, | 
			
		
	
	
		
			
				
					|  |  |  | @ -357,19 +365,21 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Apply a move to the board.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// turn must match the current turn's color, move must be valid for that player.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn apply_move(&self, turn : Color, mv : Move) -> Result<Self, Error> { | 
			
		
	
		
			
				
					|  |  |  |  |         if turn != self.turn { | 
			
		
	
		
			
				
					|  |  |  |  |             return Err(Error::NotYourTurn); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         print!("{} plays move: ", turn); | 
			
		
	
		
			
				
					|  |  |  |  |         // print!("{} plays move: ", turn);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut next = self.clone(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         match mv { | 
			
		
	
		
			
				
					|  |  |  |  |             Move::InBoard(from, to) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 println!("In-board {} -> {}", from, to); | 
			
		
	
		
			
				
					|  |  |  |  |                 // println!("In-board {} -> {}", from, to);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (self.turn == Color::White && to >= from) || (self.turn == Color::Black && to <= from) { | 
			
		
	
		
			
				
					|  |  |  |  |                     return Err(Error::MalformedMove); | 
			
		
	
	
		
			
				
					|  |  |  | @ -397,7 +407,7 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if let Some(c) = old_color { | 
			
		
	
		
			
				
					|  |  |  |  |                     if c != self.turn { | 
			
		
	
		
			
				
					|  |  |  |  |                         println!("{} stone at position {} is hit.", c, to); | 
			
		
	
		
			
				
					|  |  |  |  |                         // println!("{} stone at position {} is hit.", c, to);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                         // hit opposite color
 | 
			
		
	
		
			
				
					|  |  |  |  |                         next.other_mut().to_place += 1; | 
			
		
	
	
		
			
				
					|  |  |  | @ -405,7 +415,7 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |  |             Move::Enter(pos) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 println!("Enter -> {}", pos); | 
			
		
	
		
			
				
					|  |  |  |  |                 // println!("Enter -> {}", pos);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if self.player().to_place == 0 { | 
			
		
	
		
			
				
					|  |  |  |  |                     return Err(Error::NothingToPlace); | 
			
		
	
	
		
			
				
					|  |  |  | @ -436,14 +446,14 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if let Some(c) = old_color { | 
			
		
	
		
			
				
					|  |  |  |  |                     if c != self.turn { | 
			
		
	
		
			
				
					|  |  |  |  |                         println!("{} stone at position {} is hit.", c, pos); | 
			
		
	
		
			
				
					|  |  |  |  |                         // println!("{} stone at position {} is hit.", c, pos);
 | 
			
		
	
		
			
				
					|  |  |  |  |                         // hit opposite color
 | 
			
		
	
		
			
				
					|  |  |  |  |                         next.other_mut().to_place += 1; | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |  |             Move::BearOff(pos) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 println!("Bear off -> {}", pos); | 
			
		
	
		
			
				
					|  |  |  |  |                 // println!("Bear off -> {}", pos);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (self.turn == Color::White && pos > HOME_MAX) || (self.turn == Color::Black && pos < 18) { | 
			
		
	
		
			
				
					|  |  |  |  |                     return Err(Error::MalformedMove); | 
			
		
	
	
		
			
				
					|  |  |  | @ -469,25 +479,128 @@ impl State { | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if next.roll.remaining_moves.is_empty() { | 
			
		
	
		
			
				
					|  |  |  |  |             next.turn = self.turn.opposite(); | 
			
		
	
		
			
				
					|  |  |  |  |             next.move_number += 1; | 
			
		
	
		
			
				
					|  |  |  |  |             next.roll_mut(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // TODO check if any moves are possible with this roll, if not, auto-switch again
 | 
			
		
	
		
			
				
					|  |  |  |  |             next = next.yield_turn(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(next) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn yield_turn(&self) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut next = self.clone(); | 
			
		
	
		
			
				
					|  |  |  |  |         next.turn = self.turn.opposite(); | 
			
		
	
		
			
				
					|  |  |  |  |         next.turn_number += 1; | 
			
		
	
		
			
				
					|  |  |  |  |         next.roll_mut(); | 
			
		
	
		
			
				
					|  |  |  |  |         next | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Inject a faked dice roll
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn spoof_roll(&self, roll : Roll) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut next = self.clone(); | 
			
		
	
		
			
				
					|  |  |  |  |         next.roll = roll; | 
			
		
	
		
			
				
					|  |  |  |  |         next | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Rull dice (in place)
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn roll_mut(&mut self) { | 
			
		
	
		
			
				
					|  |  |  |  |         self.roll = Roll::new(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn get_max_number_of_possible_moves_with_current_roll(&self) -> usize { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut max = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         let color = self.turn; | 
			
		
	
		
			
				
					|  |  |  |  |         let turn_number = self.turn_number; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         k_permutation(&self.roll.remaining_moves, self.roll.remaining_moves.len(), |permuted| { | 
			
		
	
		
			
				
					|  |  |  |  |             if max == self.roll.remaining_moves.len() { | 
			
		
	
		
			
				
					|  |  |  |  |                 // There is nothing more to look for, discard the remaining iterations (sadly, can't break;)
 | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             let mut to_try = vec![self.clone()]; | 
			
		
	
		
			
				
					|  |  |  |  |             let mut to_try_next_roll = vec![]; | 
			
		
	
		
			
				
					|  |  |  |  |             for (n, roll) in permuted.iter().copied().enumerate() { | 
			
		
	
		
			
				
					|  |  |  |  |                 let depth = n + 1; | 
			
		
	
		
			
				
					|  |  |  |  |                 to_try_next_roll.clear(); | 
			
		
	
		
			
				
					|  |  |  |  |                 for state in to_try.drain(..) { | 
			
		
	
		
			
				
					|  |  |  |  |                     for mv in PossibleMovesOfLen::new(&state, roll) { | 
			
		
	
		
			
				
					|  |  |  |  |                         if let Ok(next) = state.apply_move(color, mv) { | 
			
		
	
		
			
				
					|  |  |  |  |                             max = max.max(depth); | 
			
		
	
		
			
				
					|  |  |  |  |                             if next.turn_number == turn_number { | 
			
		
	
		
			
				
					|  |  |  |  |                                 to_try_next_roll.push(next); | 
			
		
	
		
			
				
					|  |  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 std::mem::swap(&mut to_try, &mut to_try_next_roll) | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         max | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | struct PossibleMovesOfLen<'a> { | 
			
		
	
		
			
				
					|  |  |  |  |     state : &'a State, | 
			
		
	
		
			
				
					|  |  |  |  |     pos : i8, | 
			
		
	
		
			
				
					|  |  |  |  |     step: i8, | 
			
		
	
		
			
				
					|  |  |  |  |     len : u8 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl<'a> PossibleMovesOfLen<'a> { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn new(state : &'a State, len : u8) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Self { | 
			
		
	
		
			
				
					|  |  |  |  |             state, | 
			
		
	
		
			
				
					|  |  |  |  |             pos: -1, | 
			
		
	
		
			
				
					|  |  |  |  |             step: if state.turn == Color::White { | 
			
		
	
		
			
				
					|  |  |  |  |                 -(len as i8) | 
			
		
	
		
			
				
					|  |  |  |  |             } else { | 
			
		
	
		
			
				
					|  |  |  |  |                 len as i8 | 
			
		
	
		
			
				
					|  |  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |  |             len | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl<'a> Iterator for PossibleMovesOfLen<'a> { | 
			
		
	
		
			
				
					|  |  |  |  |     type Item = Move; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn next(&mut self) -> Option<Move> { | 
			
		
	
		
			
				
					|  |  |  |  |         if self.pos > 23 { | 
			
		
	
		
			
				
					|  |  |  |  |             return None; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let state = self.state; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if state.player().to_place > 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             let p = if state.turn == Color::White { | 
			
		
	
		
			
				
					|  |  |  |  |                 24 - self.len | 
			
		
	
		
			
				
					|  |  |  |  |             } else { | 
			
		
	
		
			
				
					|  |  |  |  |                 self.len | 
			
		
	
		
			
				
					|  |  |  |  |             }; | 
			
		
	
		
			
				
					|  |  |  |  |             if state.board.can_place(p, state.turn) { | 
			
		
	
		
			
				
					|  |  |  |  |                 self.pos = 24; // no more moves
 | 
			
		
	
		
			
				
					|  |  |  |  |                 return Some(Move::Enter(p)); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         'next: loop { | 
			
		
	
		
			
				
					|  |  |  |  |             self.pos += 1; | 
			
		
	
		
			
				
					|  |  |  |  |             if self.pos > 23 { | 
			
		
	
		
			
				
					|  |  |  |  |                 return None; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if state.board.can_move_from(self.pos as u8, state.turn) { | 
			
		
	
		
			
				
					|  |  |  |  |                 let dest = self.pos + self.step; | 
			
		
	
		
			
				
					|  |  |  |  |                 if dest < 0 || dest > 23 { | 
			
		
	
		
			
				
					|  |  |  |  |                     return Some(Move::BearOff(self.pos as u8)); | 
			
		
	
		
			
				
					|  |  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |  |                     if state.board.can_place(dest as u8, state.turn) { | 
			
		
	
		
			
				
					|  |  |  |  |                         return Some(Move::InBoard(self.pos as u8, dest as u8)); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl Display for State { | 
			
		
	
	
		
			
				
					|  |  |  | @ -505,11 +618,17 @@ impl Display for State { | 
			
		
	
		
			
				
					|  |  |  |  |                self.player().to_place | 
			
		
	
		
			
				
					|  |  |  |  |         )?; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         f.write_str("White <- ")?; | 
			
		
	
		
			
				
					|  |  |  |  |         if self.turn == Color::White { | 
			
		
	
		
			
				
					|  |  |  |  |             f.write_str("\x1b[1m")?; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         f.write_str("White <- \x1b[m")?; | 
			
		
	
		
			
				
					|  |  |  |  |         for n in 0..=23 { | 
			
		
	
		
			
				
					|  |  |  |  |             write!(f, "{:02}   ", n+1)?; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         f.write_str(" -> Black\n")?; | 
			
		
	
		
			
				
					|  |  |  |  |         if self.turn == Color::Black { | 
			
		
	
		
			
				
					|  |  |  |  |             f.write_str("\x1b[1m")?; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         f.write_str(" -> Black\x1b[m\n")?; | 
			
		
	
		
			
				
					|  |  |  |  |         f.write_str("         ")?; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         for n in 0..=23 { | 
			
		
	
	
		
			
				
					|  |  |  | 
 |