board.rs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  1. use bitboard::*;
  2. use movegen::*;
  3. use log::info;
  4. use std::sync::Arc;
  5. use zobrist::{ZobristTable, Hash};
  6. use crate::movegen;
  7. #[derive(Clone)]
  8. pub struct Board
  9. {
  10. pub pieces: [Bitboard; 12],
  11. pub turn: Side,
  12. /// None if no en passant move is possible,
  13. /// otherwise contains the file of the last (double-) pushed pawn
  14. pub en_passant: Option<u8>,
  15. ///
  16. /// castling rights in the following order
  17. /// white kingside, white queenside, black kingside, black queenside
  18. ///
  19. pub castling_rights: [bool; 4],
  20. //
  21. // non-hashed part
  22. // vvv
  23. pub turn_number: i32,
  24. pub halfmoves_since_last_event: i8,
  25. pub zobrist: Option<(Arc<ZobristTable>, Hash)>
  26. }
  27. impl Default for Board {
  28. fn default () -> Board {
  29. Board {
  30. pieces: [
  31. ROW_2,
  32. 0x42,
  33. 0x24,
  34. 0x81,
  35. 0x10,
  36. 0x08,
  37. ROW_7,
  38. 0x42 << 56,
  39. 0x24 << 56,
  40. 0x81 << 56,
  41. 0x10 << 56,
  42. 0x08 << 56,
  43. ],
  44. turn: WHITE,
  45. en_passant: None,
  46. castling_rights: [true; 4],
  47. halfmoves_since_last_event: 0,
  48. turn_number: 0,
  49. zobrist: None
  50. }
  51. }
  52. }
  53. impl std::hash::Hash for Board {
  54. fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
  55. if let Some((ref _zt, ref zb)) = &self.zobrist {
  56. zb.hash(state);
  57. }
  58. }
  59. }
  60. impl PartialEq for Board {
  61. fn eq(&self, other: &Self) -> bool {
  62. self.pieces == other.pieces &&
  63. self.turn == other.turn &&
  64. self.en_passant == other.en_passant &&
  65. self.castling_rights == other.castling_rights
  66. }
  67. }
  68. impl Eq for Board {
  69. }
  70. impl Board {
  71. pub fn empty() -> Board {
  72. Board {
  73. pieces: [0; 12],
  74. turn: WHITE,
  75. en_passant: None,
  76. castling_rights: [true; 4],
  77. halfmoves_since_last_event: 0,
  78. turn_number: 0,
  79. zobrist: None
  80. }
  81. }
  82. pub fn from_fen(fen: &[&str]) -> Option<Board> {
  83. let mut game: Board = Board::empty();
  84. //let example = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
  85. let position = fen[0];
  86. let turn = fen[1];
  87. let castling_rights = fen[2];
  88. let en_passant = fen[3];
  89. let halfmoves_since_last_event = fen[4];
  90. let turn_number = fen[5];
  91. {
  92. let rows = position.split('/');
  93. let mut row_index: i32 = 7;
  94. for row in rows {
  95. if row_index < 0 {
  96. return None;
  97. }
  98. let mut col_index = 0;
  99. for c in row.chars() {
  100. if col_index >= 8 {
  101. return None;
  102. }
  103. let bit_to_set = from_indices(col_index, row_index as _);
  104. match c {
  105. 'p' => { *game.pawns_mut(BLACK) |= bit_to_set },
  106. 'n' => { *game.knights_mut(BLACK) |= bit_to_set },
  107. 'b' => { *game.bishops_mut(BLACK) |= bit_to_set },
  108. 'r' => { *game.rooks_mut(BLACK) |= bit_to_set },
  109. 'q' => { *game.queens_mut(BLACK) |= bit_to_set },
  110. 'k' => { *game.kings_mut(BLACK) |= bit_to_set },
  111. 'P' => { *game.pawns_mut(WHITE) |= bit_to_set },
  112. 'N' => { *game.knights_mut(WHITE) |= bit_to_set },
  113. 'B' => { *game.bishops_mut(WHITE) |= bit_to_set },
  114. 'R' => { *game.rooks_mut(WHITE) |= bit_to_set },
  115. 'Q' => { *game.queens_mut(WHITE) |= bit_to_set },
  116. 'K' => { *game.kings_mut(WHITE) |= bit_to_set },
  117. num => {
  118. col_index += match num.to_digit(10) {
  119. Some(x) => x,
  120. None => { return None; }
  121. } as u8 - 1;
  122. }
  123. }
  124. col_index += 1;
  125. }
  126. row_index -= 1;
  127. }
  128. }
  129. if turn == "b" {
  130. game.turn = BLACK
  131. }
  132. // parse castling rights
  133. game.castling_rights[0] = castling_rights.contains('K');
  134. game.castling_rights[1] = castling_rights.contains('Q');
  135. game.castling_rights[2] = castling_rights.contains('k');
  136. game.castling_rights[3] = castling_rights.contains('q');
  137. // parse en passant
  138. game.en_passant = Move::parse_square(en_passant).map(|sq| indices_from_square(sq).0);
  139. //info!("en passant on file {:?}", game.en_passant);
  140. game.halfmoves_since_last_event = halfmoves_since_last_event.parse::<i8>().unwrap_or(0);
  141. game.turn_number = turn_number.parse::<i32>().unwrap_or(0);
  142. Some(game)
  143. }
  144. pub fn from_fen_str(fen: &str) -> Option<Board> {
  145. let fen_parts = fen.split_whitespace();
  146. Self::from_fen(fen_parts.collect::<Vec<&str>>().as_slice())
  147. }
  148. pub fn parse_move(&self, mov: &str) -> Result<Move, String> {
  149. if mov.len() < 4 {
  150. Err("string too short".to_owned())
  151. }
  152. else {
  153. let origin = Move::parse_square(&mov[0..2]);
  154. let target = Move::parse_square(&mov[2..4]);
  155. let promote_to = if mov.len() == 5 {
  156. Some(match mov.chars().nth(4) {
  157. Some('Q') | Some('q') => QUEEN,
  158. Some('N') | Some('n') => KNIGHT,
  159. Some('B') | Some('b') => BISHOP,
  160. Some('R') | Some('r') => ROOK,
  161. _ => return Err("invalid promotion".to_owned())
  162. })
  163. }
  164. else {
  165. None
  166. };
  167. if let (Some(from), Some(to)) = (origin, target) {
  168. let (piece_type, side) = self.get_square(from).ok_or("no piece at from square")?;
  169. //println!("from: {}", from);
  170. let target = self.get_square(to);
  171. let captured = if let Some((cap, _side)) = target { Some(cap) } else { None };
  172. if let Some((_cap, cs)) = target {
  173. if cs == side {
  174. return Err("cannot capture own piece".to_owned());
  175. }
  176. }
  177. if side != self.turn {
  178. return Err("wrong side to move".to_owned());
  179. }
  180. if let Some(promote_to) = promote_to {
  181. if piece_type != PAWN {
  182. // should never happen
  183. return Err("cannot promote to pawn".to_owned());
  184. }
  185. Ok(Move::Promotion{ mov: SimpleMove{ from, to }, pc: PieceCaptureType::new(promote_to, captured) })
  186. }
  187. else {
  188. if piece_type == KING && (from as i32 - to as i32).abs() == 2 {
  189. let left = from < to;
  190. //println!("OMG castling!");
  191. return Ok(Move::Castling{ mov: SimpleMove { from, to }, side, left });
  192. }
  193. // pawn capture
  194. let (from_file, from_row) = indices_from_square(from);
  195. let (target_file, _target_row) = indices_from_square(to);
  196. if piece_type == PAWN && from_file != target_file {
  197. let others = self.get_all_side(!side);
  198. if others & from_square(to) == 0 {
  199. let beaten = square_from_indices(target_file, from_row);
  200. return Ok(Move::EnPassant{ mov: SimpleMove{ from, to }, beaten });
  201. }
  202. }
  203. //println!("pt: {}", piece_type);
  204. Ok(Move::Default{ mov: SimpleMove{ from, to }, pc: PieceCaptureType::new(piece_type, captured) })
  205. }
  206. }
  207. else {
  208. Err("no valid squares".to_owned())
  209. }
  210. }
  211. }
  212. pub fn bitboard(&self, pt: PieceType, side: Side) -> Bitboard {
  213. if side == BLACK {
  214. self.pieces[(pt + 6) as usize]
  215. } else {
  216. self.pieces[pt as usize]
  217. }
  218. }
  219. /**
  220. * finds the first bitboard that has overlapping bits with the given bitboard
  221. * and returns the piece type of that bitboard
  222. */
  223. pub fn find_piece(&self, bitboard: Bitboard) -> Option<PieceType> {
  224. for i in 0..12 {
  225. if self.pieces[i] & bitboard != 0 {
  226. return Some(if i >= 6 { i - 6 } else { i } as PieceType);
  227. }
  228. }
  229. return None;
  230. }
  231. /**
  232. * \return bitboard containig all occupied squares
  233. */
  234. pub fn occupied(&self) -> Bitboard {
  235. self.pieces.iter().fold(0, |a, b| { a | b } )
  236. }
  237. pub fn pawns(&self, side: Side) -> Bitboard {
  238. match side {
  239. WHITE => self.pieces[0],
  240. BLACK => self.pieces[6],
  241. }
  242. }
  243. pub fn knights(&self, side: Side) -> Bitboard {
  244. match side {
  245. WHITE => self.pieces[1],
  246. BLACK => self.pieces[7],
  247. }
  248. }
  249. pub fn bishops(&self, side: Side) -> Bitboard {
  250. match side {
  251. WHITE => self.pieces[2],
  252. BLACK => self.pieces[8],
  253. }
  254. }
  255. pub fn rooks(&self, side: Side) -> Bitboard {
  256. match side {
  257. WHITE => self.pieces[3],
  258. BLACK => self.pieces[9],
  259. }
  260. }
  261. pub fn queens(&self, side: Side) -> Bitboard {
  262. match side {
  263. WHITE => self.pieces[4],
  264. BLACK => self.pieces[10],
  265. }
  266. }
  267. pub fn kings(&self, side: Side) -> Bitboard {
  268. match side {
  269. WHITE => self.pieces[5],
  270. BLACK => self.pieces[11],
  271. }
  272. }
  273. pub fn pawns_mut(&mut self, side: Side) -> &mut Bitboard {
  274. match side {
  275. WHITE => &mut self.pieces[0],
  276. BLACK => &mut self.pieces[6],
  277. }
  278. }
  279. pub fn knights_mut(&mut self, side: Side) -> &mut Bitboard {
  280. match side {
  281. WHITE => &mut self.pieces[1],
  282. BLACK => &mut self.pieces[7],
  283. }
  284. }
  285. pub fn bishops_mut(&mut self, side: Side) -> &mut Bitboard {
  286. match side {
  287. WHITE => &mut self.pieces[2],
  288. BLACK => &mut self.pieces[8],
  289. }
  290. }
  291. pub fn rooks_mut(&mut self, side: Side) -> &mut Bitboard {
  292. match side {
  293. WHITE => &mut self.pieces[3],
  294. BLACK => &mut self.pieces[9],
  295. }
  296. }
  297. pub fn queens_mut(&mut self, side: Side) -> &mut Bitboard {
  298. match side {
  299. WHITE => &mut self.pieces[4],
  300. BLACK => &mut self.pieces[10],
  301. }
  302. }
  303. pub fn kings_mut(&mut self, side: Side) -> &mut Bitboard {
  304. match side {
  305. WHITE => &mut self.pieces[5],
  306. BLACK => &mut self.pieces[11],
  307. }
  308. }
  309. pub fn get_piece(&self, piece_type: PieceType, side: Side) -> Bitboard {
  310. match side {
  311. WHITE => self.pieces[piece_type as usize],
  312. BLACK => self.pieces[piece_type as usize + 6],
  313. }
  314. }
  315. pub fn set_piece(&mut self, piece_type: PieceType, side: Side, bitboard: Bitboard) {
  316. match side {
  317. WHITE => self.pieces[piece_type as usize] = bitboard,
  318. BLACK => self.pieces[piece_type as usize + 6] = bitboard,
  319. }
  320. }
  321. pub fn get_piece_mut(&mut self, piece_type: PieceType, side: Side) -> &mut Bitboard {
  322. match side {
  323. WHITE => &mut self.pieces[piece_type as usize],
  324. BLACK => &mut self.pieces[piece_type as usize + 6],
  325. }
  326. }
  327. pub fn get_all_side(&self, side: Side) -> Bitboard {
  328. match side {
  329. WHITE => self.pieces[0] | self.pieces[1] | self.pieces[2] | self.pieces[3] |
  330. self.pieces[4] | self.pieces[5],
  331. BLACK => self.pieces[6] | self.pieces[7] | self.pieces[8] | self.pieces[9] |
  332. self.pieces[10] | self.pieces[11]
  333. }
  334. }
  335. pub fn get_square(&self, square: Square) -> Option<(PieceType, Side)> {
  336. let square_mask = 1 << square;
  337. for i in 0..6 {
  338. if self.pieces[i] & square_mask != 0 {
  339. return Some((i as PieceType, WHITE));
  340. }
  341. }
  342. for i in 0..6 {
  343. if self.pieces[i + 6] & square_mask != 0 {
  344. return Some((i as PieceType, BLACK));
  345. }
  346. }
  347. return None;
  348. }
  349. /**
  350. * @brief masks all bitboards.
  351. */
  352. pub fn apply_mask(&mut self, mask: Bitboard) {
  353. for board in &mut self.pieces {
  354. *board &= mask;
  355. }
  356. }
  357. /**
  358. * @brief creates a unicode string containing the board
  359. *
  360. * Example:
  361. *
  362. * ┌───┬───┬───┬───┬───┬───┬───┬───┐
  363. * 8 │ ♜ │ ♞ │ ♝ │ ♛ │ ♚ │ ♝ │ ♞ │ ♜ │
  364. * ├───┼───┼───┼───┼───┼───┼───┼───┤
  365. * 7 │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │
  366. * ├───┼───┼───┼───┼───┼───┼───┼───┤
  367. * 6 │ │ │ │ │ │ │ │ │
  368. * ├───┼───┼───┼───┼───┼───┼───┼───┤
  369. * 5 │ │ │ │ │ │ │ │ │
  370. * ├───┼───┼───┼───┼───┼───┼───┼───┤
  371. * 4 │ │ │ │ │ │ │ │ │
  372. * ├───┼───┼───┼───┼───┼───┼───┼───┤
  373. * 3 │ │ │ │ │ │ │ │ │
  374. * ├───┼───┼───┼───┼───┼───┼───┼───┤
  375. * 2 │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │
  376. * ├───┼───┼───┼───┼───┼───┼───┼───┤
  377. * 1 │ ♖ │ ♘ │ ♗ │ ♕ │ ♔ │ ♗ │ ♘ │ ♖ │
  378. * └───┴───┴───┴───┴───┴───┴───┴───┘
  379. * a b c d e f g h
  380. *
  381. */
  382. pub fn beautiful_print(&self) -> String {
  383. let chars = ['─', '│', '┌', '┐', '└', '┘', '├', '┤', '┬', '┴', '┼'];
  384. let figures = ['♙', '♘', '♗', '♖', '♕', '♔', '♟', '♞', '♝', '♜', '♛', '♚'];
  385. let mut board: String = String::new();
  386. #[derive(Copy, Clone)]
  387. struct GridLine {
  388. left: char,
  389. center: char,
  390. right: char,
  391. }
  392. let top = GridLine { left: chars[2], center: chars[8], right: chars[3] };
  393. let center = GridLine { left: chars[6], center: chars[10], right: chars[7] };
  394. let bot = GridLine { left: chars[4], center: chars[9], right: chars[5] };
  395. let generate_line = |gl: GridLine| {
  396. let mut line = String::new();
  397. for i in 0..33 {
  398. match i {
  399. 0 => { line.push(gl.left) }
  400. 32 => { line.push(gl.right) }
  401. x => { line.push(if x % 4 == 0 { gl.center } else { chars[0] }) }
  402. }
  403. }
  404. return line;
  405. };
  406. let piece_line = |row: u8| {
  407. let mut line = String::new();
  408. line.push(chars[1]);
  409. line.push(' ');
  410. for i in 0..8 {
  411. if let Some((pt, side)) = self.get_square(square_from_indices(i, 7 - row)) {
  412. let fig_index = pt as usize + if side == BLACK { 6 } else { 0 };
  413. line.push(figures[fig_index]);
  414. }
  415. else {
  416. line.push(' ');
  417. }
  418. line.push(' '); line.push(chars[1]); line.push(' ');
  419. }
  420. return line;
  421. };
  422. board.push_str(" ");
  423. board.push_str(&generate_line(top));
  424. board.push('\n');
  425. for i in 0..8 {
  426. board.push_str(&(8 - i).to_string());
  427. board.push(' ');
  428. board.push_str(&piece_line(i));
  429. board.push('\n');
  430. if i != 7 {
  431. board.push_str(" ");
  432. board.push_str(&generate_line(center));
  433. board.push('\n');
  434. }
  435. }
  436. board.push_str(" ");
  437. board.push_str(&generate_line(bot));
  438. board.push_str("\n a b c d e f g h");
  439. let chars = ['K', 'Q', 'k', 'q'];
  440. let mut cr: [char; 4] = [' '; 4];
  441. for i in 0..4 {
  442. cr[i] = if self.castling_rights[i] {
  443. chars[i]
  444. } else { ' ' };
  445. }
  446. if self.turn == WHITE {
  447. board.push_str("\nWhite to move\n");
  448. }
  449. else {
  450. board.push_str("\nBlack to move\n");
  451. }
  452. board.push_str(&format!("\nCastling : {}{}{}{}", cr[0], cr[1], cr[2], cr[3]));
  453. board.push_str(&format!("\nEn Passant : {}", self.en_passant.map(|f| f.to_string()).unwrap_or("-".to_owned())));
  454. board.push_str(&format!("\nTurn number : {}", self.turn_number));
  455. board.push_str(&format!("\nHalfmoves slt : {}", self.halfmoves_since_last_event));
  456. return board;
  457. }
  458. pub fn update_zobrist(&mut self, h: Hash) {
  459. if let Some((ref _zt, ref mut zh)) = self.zobrist {
  460. *zh ^= h;
  461. }
  462. }
  463. pub fn calculate_zobrist(&self, zt: &ZobristTable) -> Hash {
  464. let mut hash: Hash = 0;
  465. for pt in 0..6 {
  466. let bb_it_w = BitboardIterator(self.get_piece(pt, WHITE));
  467. let bb_it_b = BitboardIterator(self.get_piece(pt, BLACK));
  468. for bb_square in bb_it_w {
  469. hash ^= zt.piece_hash(pt as _, WHITE, square(bb_square));
  470. }
  471. for bb_square in bb_it_b {
  472. hash ^= zt.piece_hash(pt as _, BLACK, square(bb_square));
  473. }
  474. }
  475. for cr_id in 0..4 {
  476. if self.castling_rights[cr_id] {
  477. hash ^= zt.castling_rights_hash(cr_id as _);
  478. }
  479. }
  480. if let Some(file) = self.en_passant {
  481. hash ^= zt.en_passant_hash(file);
  482. }
  483. if self.turn {
  484. hash ^= zt.turn_hash();
  485. }
  486. return hash;
  487. }
  488. pub fn is_zobrist_correct(&self) -> bool {
  489. if let Some((ref zt, zv)) = self.zobrist {
  490. self.calculate_zobrist(zt) == zv
  491. }
  492. else {
  493. false
  494. }
  495. }
  496. ///
  497. /// TODO: improve
  498. ///
  499. pub fn is_legal(&self, mov: Move) -> bool {
  500. /*match mov {
  501. Move::Default { mov, pc } => {
  502. let piece_type = pc.piece_type();
  503. let capture = pc.capture_type();
  504. let legal_from = self.get_piece(piece_type, self.turn);
  505. match piece_type {
  506. PAWN => {
  507. if pawn
  508. }
  509. }
  510. }
  511. }*/
  512. movegen::generate_legal_moves(&mut self.clone(), self.turn, false).contains(&mov)
  513. }
  514. pub fn apply(&mut self, mov: Move) -> MoveUndo {
  515. /*if !self.is_zobrist_correct() {
  516. println!("{}", self.beautiful_print());
  517. println!("incorrect zobrist before apply {} {:?}", mov.to_string(), mov);
  518. info!("incorrect zobrist before apply");
  519. panic!("zobrist");
  520. let val = if let Some((ref zt, _zv)) = self.zobrist {
  521. self.calculate_zobrist(zt)
  522. } else { 0 };
  523. if let Some((ref _zt, ref mut zv)) = self.zobrist {
  524. *zv = val;
  525. }
  526. }*/
  527. // save irrecoverable values
  528. let castling_rights_before = self.castling_rights.clone();
  529. let halfmoves_since_last_event_before = self.halfmoves_since_last_event.clone();
  530. let en_passant_before = self.en_passant;
  531. let side = self.turn;
  532. let others = self.get_all_side(!side);
  533. if !mov.is_null() {
  534. match mov {
  535. Move::Default{ mov, pc } => {
  536. let pt = pc.piece_type();
  537. if pt == KING {
  538. // invalidate castling rights
  539. self.castling_rights[if side == BLACK { 2 } else { 0 }] = false;
  540. self.castling_rights[if side == BLACK { 3 } else { 1 }] = false;
  541. }
  542. // invalidate castling rights
  543. if mov.from == square_from_indices(7, 0) || mov.to == square_from_indices(7, 0) {
  544. self.castling_rights[0] = false;
  545. }
  546. if mov.from == square_from_indices(0, 0) || mov.to == square_from_indices(0, 0) {
  547. self.castling_rights[1] = false;
  548. }
  549. if mov.from == square_from_indices(7, 7) || mov.to == square_from_indices(7, 7) {
  550. self.castling_rights[2] = false;
  551. }
  552. if mov.from == square_from_indices(0, 7) || mov.to == square_from_indices(0, 7) {
  553. self.castling_rights[3] = false;
  554. }
  555. // if it is a capture
  556. if from_square(mov.to) & others != 0 {
  557. if let Some((other_piece, other_side)) = self.get_square(mov.to) {
  558. // update zobrist
  559. if let Some((ref zt, ref mut zv)) = self.zobrist {
  560. let hup = zt.piece_hash(other_piece, other_side, mov.to);
  561. *zv ^= hup;
  562. }
  563. *self.get_piece_mut(other_piece, other_side) &= !from_square(mov.to);
  564. }
  565. }
  566. // reset en passant and then check if possible
  567. self.en_passant = None;
  568. if pt == PAWN {
  569. let row1 = indices_from_square(mov.from).1;
  570. let row2 = indices_from_square(mov.to).1;
  571. // check for double push
  572. if i32::abs(row1 as i32 - row2 as i32) >= 2 {
  573. let opponent_pawns = self.get_piece(PAWN, !side);
  574. let target_bb = from_square(mov.to);
  575. if (west_one(target_bb) | east_one(target_bb)) & opponent_pawns != 0 {
  576. self.en_passant = Some(indices_from_square(mov.to).0);
  577. }
  578. }
  579. }
  580. let moved_piece = mov.apply_to(self.get_piece(pt, side));
  581. self.set_piece(pt, side, moved_piece);
  582. if let Some((ref zt, ref mut zv)) = self.zobrist {
  583. let hup = zt.piece_hash(pt, side, mov.from) ^ zt.piece_hash(pt, side, mov.to);
  584. *zv ^= hup;
  585. }
  586. },
  587. Move::Castling { mov:_, side, left } => {
  588. // invalidate future castling rights
  589. self.castling_rights[if side == BLACK { 2 } else { 0 }] = false;
  590. self.castling_rights[if side == BLACK { 3 } else { 1 }] = false;
  591. let king = self.get_piece(KING, side);
  592. let rook = if left {
  593. self.get_piece(ROOK, side) & (king << 4)
  594. }
  595. else {
  596. self.get_piece(ROOK, side) & (king >> 3)
  597. };
  598. let new_king = if left { king << 2 } else { king >> 2 };
  599. let new_rook = if left { rook >> 3 } else { rook << 2 };
  600. self.set_piece(KING, side, new_king);
  601. *self.get_piece_mut(ROOK, side) &= !rook;
  602. *self.get_piece_mut(ROOK, side) |= new_rook;
  603. if let Some((ref zt, ref mut zv)) = self.zobrist {
  604. let hupk = zt.piece_hash(KING, side, square(king)) ^ zt.piece_hash(KING, side, square(new_king));
  605. let hup = zt.piece_hash(ROOK, side, square(rook)) ^ zt.piece_hash(ROOK, side, square(new_rook));
  606. *zv ^= hup ^ hupk;
  607. }
  608. self.en_passant = None;
  609. },
  610. Move::EnPassant { mov, beaten } => {
  611. if let Some(_ep) = self.en_passant {
  612. *self.get_piece_mut(PAWN, side) &= !from_square(mov.from);
  613. *self.get_piece_mut(PAWN, side) |= from_square(mov.to);
  614. *self.get_piece_mut(PAWN, !side) &= !from_square(beaten);
  615. if let Some((ref zt, ref mut zv)) = self.zobrist {
  616. let hup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(PAWN, side, mov.to);
  617. let hupo = zt.piece_hash(PAWN, !side, beaten);
  618. *zv ^= hup ^ hupo;
  619. }
  620. self.en_passant = None;
  621. }
  622. else {
  623. info!("internal en passant error");
  624. panic!("internal en passant error");
  625. }
  626. },
  627. Move::Promotion { mov, pc } => {
  628. let promote_to = pc.piece_type();
  629. let captured = pc.capture_type();
  630. //if from_square(mov.to) & others != 0 {
  631. if let Some(pt) = captured {
  632. *self.get_piece_mut(pt, !side) &= !from_square(mov.to);
  633. if let Some((ref zt, ref mut zv)) = self.zobrist {
  634. let hup = zt.piece_hash(pt, !side, mov.to);
  635. *zv ^= hup;
  636. }
  637. }
  638. *self.get_piece_mut(PAWN, side) &= !from_square(mov.from);
  639. if let Some((ref zt, ref mut zv)) = self.zobrist {
  640. let hup = zt.piece_hash(PAWN, side, mov.from);
  641. *zv ^= hup;
  642. }
  643. match promote_to {
  644. QUEEN => { *self.queens_mut(side) |= from_square(mov.to); }
  645. ROOK => { *self.rooks_mut(side) |= from_square(mov.to); }
  646. BISHOP => { *self.bishops_mut(side) |= from_square(mov.to); }
  647. KNIGHT => { *self.knights_mut(side) |= from_square(mov.to); }
  648. _ => {
  649. info!("internal error");
  650. }
  651. }
  652. if let Some((ref zt, ref mut zv)) = self.zobrist {
  653. let hup = zt.piece_hash(promote_to, side, mov.to);
  654. *zv ^= hup;
  655. }
  656. self.en_passant = None;
  657. },
  658. }
  659. }
  660. if self.turn == BLACK {
  661. self.turn_number += 1;
  662. }
  663. self.turn = !self.turn;
  664. if let Some((ref zt, ref mut zv)) = self.zobrist {
  665. let hup = zt.turn_hash();
  666. let castling_hup = zt.all_castling_rights_hash(castling_rights_before) ^ zt.all_castling_rights_hash(self.castling_rights);
  667. let enpass_hup = en_passant_before.map(|f| zt.en_passant_hash(f)).unwrap_or(0) ^ self.en_passant.map(|f| zt.en_passant_hash(f)).unwrap_or(0);
  668. *zv ^= hup ^ castling_hup ^ enpass_hup;
  669. }
  670. /*if !self.is_zobrist_correct() {
  671. println!("{}", self.beautiful_print());
  672. println!("incorrect zobrist after apply {} {:?}", mov.to_string(), mov);
  673. info!("incorrect zobrist after apply");
  674. panic!("zobrist");
  675. let val = if let Some((ref zt, _zv)) = self.zobrist {
  676. self.calculate_zobrist(zt)
  677. } else { 0 };
  678. if let Some((ref _zt, ref mut zv)) = self.zobrist {
  679. *zv = val;
  680. }
  681. }*/
  682. MoveUndo {
  683. castling_rights_before,
  684. halfmoves_since_last_event_before,
  685. en_passant_before,
  686. mov
  687. }
  688. }
  689. pub fn undo_move(&mut self, umov: MoveUndo) {
  690. /*if !self.is_zobrist_correct() {
  691. println!("{}", self.beautiful_print());
  692. println!("incorrect zobrist before undo {} {:?}", umov.mov.to_string(), umov.mov);
  693. info!("incorrect zobrist before undo {} {:?}", umov.mov.to_string(), umov.mov);
  694. panic!("zobrist");
  695. }*/
  696. if let Some((ref zt, ref mut zv)) = self.zobrist {
  697. let crhup = zt.all_castling_rights_hash(self.castling_rights) ^ zt.all_castling_rights_hash(umov.castling_rights_before);
  698. let enpass_hup = self.en_passant.map(|f| zt.en_passant_hash(f)).unwrap_or(0) ^ umov.en_passant_before.map(|f| zt.en_passant_hash(f)).unwrap_or(0);
  699. *zv ^= crhup ^ enpass_hup;
  700. }
  701. self.castling_rights = umov.castling_rights_before;
  702. self.halfmoves_since_last_event = umov.halfmoves_since_last_event_before;
  703. self.en_passant = umov.en_passant_before;
  704. let mov = umov.mov;
  705. // the side that played the turn that is to be reverted
  706. let side = !self.turn;
  707. if !mov.is_null() {
  708. match mov {
  709. Move::Default{ mov, pc } => {
  710. let piece_type = pc.piece_type();
  711. let captured = pc.capture_type();
  712. let moved_piece_bb = self.get_piece_mut(piece_type, side);
  713. *moved_piece_bb &= !from_square(mov.to);
  714. *moved_piece_bb |= from_square(mov.from);
  715. if let Some((ref zt, ref mut zv)) = self.zobrist {
  716. let hup = zt.piece_hash(piece_type, side, mov.from) ^ zt.piece_hash(piece_type, side, mov.to);
  717. *zv ^= hup;
  718. }
  719. if let Some(pt) = captured {
  720. *self.get_piece_mut(pt, !side) |= from_square(mov.to);
  721. if let Some((ref zt, ref mut zv)) = self.zobrist {
  722. let hup = zt.piece_hash(pt, !side, mov.to);
  723. *zv ^= hup;
  724. }
  725. }
  726. },
  727. Move::Castling { mov: _, side, left } => {
  728. let king = self.get_piece(KING, side);
  729. let rook = if left {
  730. self.get_piece(ROOK, side) & (king >> 1)
  731. }
  732. else {
  733. self.get_piece(ROOK, side) & (king << 1)
  734. };
  735. let old_king = if left { king >> 2 } else { king << 2 };
  736. let old_rook = if left { rook << 3 } else { rook >> 2 };
  737. self.set_piece(KING, side, old_king);
  738. *self.get_piece_mut(ROOK, side) &= !rook;
  739. *self.get_piece_mut(ROOK, side) |= old_rook;
  740. if let Some((ref zt, ref mut zv)) = self.zobrist {
  741. let khup = zt.piece_hash(KING, side, square(old_king)) ^ zt.piece_hash(KING, side, square(king));
  742. let rhup = zt.piece_hash(ROOK, side, square(rook)) ^ zt.piece_hash(ROOK, side, square(old_rook));
  743. *zv ^= khup ^ rhup;
  744. }
  745. },
  746. Move::EnPassant { mov, beaten } => {
  747. *self.get_piece_mut(PAWN, side) |= from_square(mov.from);
  748. *self.get_piece_mut(PAWN, side) &= !from_square(mov.to);
  749. *self.get_piece_mut(PAWN, !side) |= from_square(beaten);
  750. if let Some((ref zt, ref mut zv)) = self.zobrist {
  751. let phup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(PAWN, side, mov.to);
  752. let chup = zt.piece_hash(PAWN, !side, beaten);
  753. *zv ^= phup ^ chup;
  754. }
  755. // should already be reverted
  756. //self.en_passant = Some(indices_from_square(beaten).0);
  757. },
  758. Move::Promotion { mov, pc } => {
  759. let promote_to = pc.piece_type();
  760. let captured = pc.capture_type();
  761. match promote_to {
  762. QUEEN => { *self.queens_mut(side) &= !from_square(mov.to); }
  763. ROOK => { *self.rooks_mut(side) &= !from_square(mov.to); }
  764. BISHOP => { *self.bishops_mut(side) &= !from_square(mov.to); }
  765. KNIGHT => { *self.knights_mut(side) &= !from_square(mov.to); }
  766. _ => {
  767. info!("internal error");
  768. }
  769. }
  770. *self.pawns_mut(side) |= from_square(mov.from);
  771. if let Some((ref zt, ref mut zv)) = self.zobrist {
  772. let hup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(promote_to, side, mov.to);
  773. *zv ^= hup;
  774. }
  775. if let Some(pt) = captured {
  776. *self.get_piece_mut(pt, !side) |= from_square(mov.to);
  777. if let Some((ref zt, ref mut zv)) = self.zobrist {
  778. let hup = zt.piece_hash(pt, !side, mov.to);
  779. *zv ^= hup;
  780. }
  781. }
  782. },
  783. }
  784. }
  785. self.turn = side;
  786. if side == BLACK {
  787. self.turn_number -= 1;
  788. }
  789. if let Some((ref zt, ref mut zv)) = self.zobrist {
  790. *zv ^= zt.turn_hash();
  791. }
  792. /*if !self.is_zobrist_correct() {
  793. println!("{}", self.beautiful_print());
  794. println!("incorrect zobrist after undo {} {:?}", umov.mov.to_string(), umov.mov);
  795. info!("incorrect zobrist after undo {} {:?}", umov.mov.to_string(), umov.mov);
  796. panic!("zobrist");
  797. }*/
  798. /*let val = if let Some((ref zt, _zv)) = self.zobrist {
  799. self.calculate_zobrist(zt)
  800. } else { 0 };
  801. if let Some((ref _zt, ref mut zv)) = self.zobrist {
  802. *zv = val;
  803. }*/
  804. }
  805. pub fn to_vector(&self) -> Vec<f64> {
  806. let mut v = Vec::new();
  807. for side in [WHITE, BLACK] {
  808. for pt in 0..6 {
  809. for sq in 0..64 {
  810. if self.get_square(sq) == Some((pt, side)) {
  811. v.push(1f64);
  812. }
  813. else {
  814. v.push(0f64);
  815. }
  816. }
  817. }
  818. }
  819. v
  820. }
  821. pub fn ply_number(&self) -> i32 {
  822. self.turn_number * 2 + if self.turn == BLACK { 1 } else { 0 }
  823. }
  824. }