| 
					
				 | 
			
			
				@@ -2,45 +2,79 @@ use game::*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use bitboard::*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use movegen::*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-use std::f32::*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::i32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-pub type PosValue = f32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-pub const MIN_VALUE: PosValue = -1000000.0f32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-pub const MAX_VALUE: PosValue = 1000000.0f32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub type PosValue = i32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-fn value_castling_rights(game: &Game, side: Side) -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let mut val: PosValue = 0.0f32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub const MIN_VALUE: PosValue = i32::MIN + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub const MAX_VALUE: PosValue = i32::MAX; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for i in 0..2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if game.castling_rights[i] { val += 12.0f32; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const MATE_SHIFT: usize = 24; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub fn mate() -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mate_in_p1(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * constructs a PosValue that indicates that from a given position mate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * can be achieved in turns-1 moves (not halfmoves) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub fn mate_in_p1(turns: i8) -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if turns >= 0 || turns == -128 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        (((127 - turns) as PosValue) << MATE_SHIFT) as i32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for i in 2..4 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if game.castling_rights[i] { val -= 12.0f32; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        -mate_in_p1(-turns) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if side == BLACK { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -val; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * returns Some(turns) if the pos_val indicates that mate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * can be reached in turns-1 moves 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * turns is negative if the moving side is getting mated 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * in turns moves 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub fn is_mate_in_p1(pos_val: PosValue) -> Option<i8> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let highest_byte = (pos_val >> MATE_SHIFT) as i8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if highest_byte != 0 && highest_byte != -1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if pos_val < 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Some(-127 - highest_byte) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Some(127 - highest_byte) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return val; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 fn side_value(game: &Game, side: Side) -> u32 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let adv_pawn_mask = match side { WHITE => ROW_7, BLACK => ROW_2 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let semi_adv_pawn_mask = match side { WHITE => ROW_6, BLACK => ROW_3 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let advanced_pawns = (game.get_piece(PAWN, side) & adv_pawn_mask).count_ones() * 200; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let semi_advanced_pawns = (game.get_piece(PAWN, side) & semi_adv_pawn_mask).count_ones() * 50; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    advanced_pawns + semi_advanced_pawns 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fn knight_value(game: &Game, side: Side) -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let knights = game.get_piece(KNIGHT, side); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let ks = BitboardIterator(knights); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let mut k_attacks: u32 = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for k in ks { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let targets = get_knight_targets(square(k)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        k_attacks += targets.count_ones() * 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        k_attacks += targets.count_ones() * 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let adv_pawn_mask = match side { WHITE => ROW_7, BLACK => ROW_2 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let advanced_pawns = (game.get_piece(PAWN, side) & adv_pawn_mask).count_ones() * 200; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    advanced_pawns + k_attacks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let num_opp_pawns = game.get_piece(PAWN, !side).count_ones() as PosValue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let num_knights = game.get_piece(KNIGHT, side).count_ones() as PosValue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    k_attacks as PosValue + ((num_knights * 75 * num_opp_pawns) / 8) as PosValue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 fn material_value(game: &Game, side: Side) -> PosValue { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -51,10 +85,34 @@ fn material_value(game: &Game, side: Side) -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         + game.get_piece(QUEEN, side).count_ones() * 700) as PosValue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fn king_safety(game: &Game, side: Side) -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let king = game.get_piece(KING, side); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let area = north_one(king) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             | south_one(king) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             | east_one(king) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             | west_one(king) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             | northeast_one(king) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             | northwest_one(king) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             | southwest_one(king) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             | southeast_one(king); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let guards = game.get_all_side(side) & area; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let attackers = game.get_all_side(!side) & area; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    guards.count_ones() as PosValue * 10 - attackers.count_ones() as PosValue * 35 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fn king_there(game: &Game, side: Side) -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if game.get_piece(KING, side) != 0 { 10000 } else { 0 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 pub fn evaluate(game: &Game) -> PosValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let sv = side_value(game, game.turn) as PosValue - side_value(game, !game.turn) as PosValue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let material_value_us = material_value(game, game.turn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let material_value_them = material_value(game, !game.turn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let mat_val = material_value_us.powf(0.995f32) - material_value_them.powf(0.995f32); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return mat_val + value_castling_rights(game, game.turn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mat_val = ((material_value_us as f32).powf(0.995f32) - (material_value_them as f32).powf(0.995f32)) as PosValue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let kv = knight_value(game, game.turn) - knight_value(game, !game.turn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let king_safety = king_safety(game, game.turn) - king_safety(game, !game.turn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let king_there = king_there(game, game.turn) - king_there(game, !game.turn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return sv + kv + king_safety + mat_val + king_there; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |