[bitboard, core, position] Implement proper castle move generation
Add a field to MoveSet called special that flags special moves that should be generated in the iter() method. This field is a u8. It only tracks castles in the first and second bits (kingside and queenside, respectively). The move iterator chains two maps over Option<()> that produce the kingside and queenside castle moves. With that done, finish the implementation of Position::player_can_castle by adding checks for whether the squares between the rook and king are clear, and that the king would not pass through a check. This is done with BitBoards! Finally, implement some logic in PositionBuilder that updates the position's castling flags based on the positions of king and rooks. Supporting changes: - Add Color:ALL and iterate on that slice - Add Castle::ALL and iterator on that slice - Add a CastlingParameters struct that contains BitBoard properties that describe squares that should be clear of pieces and squares that should not be attacked.
This commit is contained in:
parent
83a4e47e56
commit
1d7dada987
6 changed files with 234 additions and 60 deletions
|
@ -1,6 +1,6 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use crate::{Move, MoveBuilder};
|
||||
use crate::{r#move::Castle, Move, MoveBuilder};
|
||||
use chessfriend_bitboard::BitBoard;
|
||||
use chessfriend_core::{Color, Piece, PlacedPiece, Shape};
|
||||
|
||||
|
@ -27,7 +27,7 @@ impl MoveListSet {
|
|||
pub(crate) struct MoveSet {
|
||||
piece: PlacedPiece,
|
||||
bitboards: BitBoardSet,
|
||||
move_lists: MoveListSet,
|
||||
special: u8,
|
||||
}
|
||||
|
||||
impl MoveSet {
|
||||
|
@ -35,10 +35,7 @@ impl MoveSet {
|
|||
MoveSet {
|
||||
piece,
|
||||
bitboards: BitBoardSet::default(),
|
||||
move_lists: MoveListSet {
|
||||
quiet: Vec::new(),
|
||||
captures: Vec::new(),
|
||||
},
|
||||
special: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +49,16 @@ impl MoveSet {
|
|||
self
|
||||
}
|
||||
|
||||
pub(super) fn kingside_castle(&mut self) -> &mut MoveSet {
|
||||
self.special |= 0b1;
|
||||
self
|
||||
}
|
||||
|
||||
pub(super) fn queenside_castle(&mut self) -> &mut MoveSet {
|
||||
self.special |= 0b10;
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a BitBoard representing all possible moves.
|
||||
pub(super) fn bitboard(&self) -> BitBoard {
|
||||
self.bitboards.captures | self.bitboards.quiet
|
||||
|
@ -78,5 +85,37 @@ impl MoveSet {
|
|||
.build()
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
if (self.special & 0b1) != 0 {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.map(|()| {
|
||||
MoveBuilder::new(
|
||||
*piece,
|
||||
from_square,
|
||||
Castle::KingSide.target_squares(piece.color()).king,
|
||||
)
|
||||
.castle(Castle::KingSide)
|
||||
.build()
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
if (self.special & 0b10) != 0 {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.map(|()| {
|
||||
MoveBuilder::new(
|
||||
*piece,
|
||||
from_square,
|
||||
Castle::QueenSide.target_squares(piece.color()).king,
|
||||
)
|
||||
.castle(Castle::QueenSide)
|
||||
.build()
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue