[position, board, core, moves] Implement a bunch of make_move code
Implement making double push and promotion moves. Then write several tests to exercise these. Add convenient static functions to the Move struct to build moves quickly, without using the Builder. Add a is_promotable_rank() method to Rank to check that a rank can be used for promotion moves. The tests found and fixed a bug in pawn movement where the en passant square was being discarded when deciding whether an e.p. move can be made.
This commit is contained in:
parent
6591619e32
commit
039fd2b080
4 changed files with 257 additions and 22 deletions
|
@ -1,7 +1,6 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::defs::Kind;
|
||||
use crate::defs::{Kind, PromotionShape};
|
||||
use chessfriend_core::{Rank, Shape, Square, Wing};
|
||||
use std::fmt;
|
||||
|
||||
|
@ -14,6 +13,48 @@ use std::fmt;
|
|||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct Move(pub(crate) u16);
|
||||
|
||||
impl Move {
|
||||
#[must_use]
|
||||
pub fn quiet(origin: Square, target: Square) -> Self {
|
||||
let origin_bits = (origin as u16) << 4;
|
||||
let target_bits = (target as u16) << 10;
|
||||
Move(origin_bits | target_bits)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn double_push(origin: Square, target: Square) -> Self {
|
||||
let origin_bits = (origin as u16) << 4;
|
||||
let target_bits = (target as u16) << 10;
|
||||
let flag_bits = Kind::DoublePush as u16;
|
||||
Move(origin_bits | target_bits | flag_bits)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn capture(origin: Square, target: Square) -> Self {
|
||||
let origin_bits = (origin as u16) << 4;
|
||||
let target_bits = (target as u16) << 10;
|
||||
let flag_bits = Kind::Capture as u16;
|
||||
Move(origin_bits | target_bits | flag_bits)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn en_passant_capture(origin: Square, target: Square) -> Self {
|
||||
let origin_bits = (origin as u16) << 4;
|
||||
let target_bits = (target as u16) << 10;
|
||||
let flag_bits = Kind::EnPassantCapture as u16;
|
||||
Move(origin_bits | target_bits | flag_bits)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn promotion(origin: Square, target: Square, shape: PromotionShape) -> Self {
|
||||
let origin_bits = (origin as u16) << 4;
|
||||
let target_bits = (target as u16) << 10;
|
||||
let flag_bits = Kind::Promotion as u16;
|
||||
let shape_bits = shape as u16;
|
||||
Move(origin_bits | target_bits | flag_bits | shape_bits)
|
||||
}
|
||||
}
|
||||
|
||||
impl Move {
|
||||
#[must_use]
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
|
@ -85,7 +126,7 @@ impl Move {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn promotion(&self) -> Option<Shape> {
|
||||
pub fn promotion_shape(&self) -> Option<Shape> {
|
||||
if !self.is_promotion() {
|
||||
return None;
|
||||
}
|
||||
|
@ -139,7 +180,7 @@ impl fmt::Display for Move {
|
|||
let transfer_char = self.transfer_char();
|
||||
write!(f, "{origin}{transfer_char}{target}")?;
|
||||
|
||||
if let Some(promotion) = self.promotion() {
|
||||
if let Some(promotion) = self.promotion_shape() {
|
||||
write!(f, "={promotion}")?;
|
||||
} else if self.is_en_passant() {
|
||||
write!(f, " e.p.")?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue