Skip to content

Commit

Permalink
Merge pull request #16 from clemenscodes/develop
Browse files Browse the repository at this point in the history
pawn logic
  • Loading branch information
clemenscodes authored Feb 14, 2024
2 parents 507d497 + adacfc1 commit 6bf7279
Show file tree
Hide file tree
Showing 55 changed files with 1,197 additions and 369 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,13 @@ jobs:
run: pnpm fmt:check

- name: Lint
run: pnpm lint:affected --nx-bail --base=$NX_BASE --head=$NX_HEAD
run: pnpm lint:affected --configuration=ci --nx-bail --base=$NX_BASE --head=$NX_HEAD --exclude gui

- name: Test
run: pnpm test:affected --nx-bail --base=$NX_BASE --head=$NX_HEAD
run: pnpm test:affected --nx-bail --base=$NX_BASE --head=$NX_HEAD --exclude gui

- name: Coverage
run: pnpm nx affected -t coverage --nx-bail --base=$NX_BASE --head=$NX_HEAD
run: pnpm coverage:affected --nx-bail --base=$NX_BASE --head=$NX_HEAD --exclude gui

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
Expand Down
5 changes: 5 additions & 0 deletions apps/ui/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"lint": {
"executor": "nx:run-commands",
"inputs": ["default", "^default"],
"configurations": {
"ci": {
"command": "eslint . --max-warnings 0"
}
},
"options": {
"color": true,
"cwd": "apps/{projectName}",
Expand Down
544 changes: 544 additions & 0 deletions assets/engine-interface.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion libs/api/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ pub trait Controller: GameExt + ForsythEdwardsNotationExt {
fn get_source(&self) -> Square;
fn get_destination(&self) -> Square;
fn get_dragged_square(&self) -> Square;
fn get_legal_moves(&self) -> Vec<(Square, Square)>;
fn get_legal_moves(&self) -> Vec<(Square, Square, Option<char>)>;
}
4 changes: 3 additions & 1 deletion libs/api/src/game.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::error::Error;

use crate::square::Square;

pub trait GameExt {
Expand All @@ -15,6 +17,6 @@ pub trait GameExt {
fn promote_knight(&mut self);
fn promote_bishop(&mut self);
fn is_own_piece_on_square(&self, square: Square) -> bool;
fn make_move(&mut self, source: Square, destination: Square) -> Result<(), ()>;
fn make_move(&mut self, source: Square, destination: Square, promotion: Option<char>) -> Result<(), Box<dyn Error>>;
fn ply(&self) -> u16;
}
2 changes: 1 addition & 1 deletion libs/api/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ use crate::{ForsythEdwardsNotationExt, GameExt, Square};

pub trait Model: GameExt + ForsythEdwardsNotationExt {
fn get_fen(&self) -> String;
fn get_legal_moves(&self, square: Square) -> Vec<(Square, Square)>;
fn get_legal_moves(&self, square: Square) -> Vec<(Square, Square, Option<char>)>;
fn clear_error(&mut self);
}
72 changes: 63 additions & 9 deletions libs/board/src/fen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ pub mod full_move_clock;
pub mod half_move_clock;
pub mod placements;

use self::{active_color::*, castling::*, enpassant::*, full_move_clock::*, half_move_clock::*, placements::*};
use api::ForsythEdwardsNotationExt;
use bitboard::Bitboard;

use self::{active_color::*, castling::*, enpassant::*, full_move_clock::*, half_move_clock::*, placements::*};
use std::fmt::{Debug, Display};
use std::{
error::Error,
fmt::{Debug, Display},
};

pub const FEN_PARTS: usize = 6;

Expand Down Expand Up @@ -106,6 +108,58 @@ pub enum ForsythEdwardsNotationError {
InvalidFullMoveClock(FullMoveClockError),
}

impl Display for ForsythEdwardsNotationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ForsythEdwardsNotationError::Invalid => write!(f, "Invalid fen"),
ForsythEdwardsNotationError::InvalidPlacements(_) => write!(f, "Invalid placement data"),
ForsythEdwardsNotationError::InvalidActiveColor(_) => write!(f, "Invalid active color"),
ForsythEdwardsNotationError::InvalidCastling(_) => write!(f, "Invalid castling information"),
ForsythEdwardsNotationError::InvalidEnPassant(_) => write!(f, "Invalid en passant square"),
ForsythEdwardsNotationError::InvalidHalfMoveClock(_) => write!(f, "Invalid half move clock"),
ForsythEdwardsNotationError::InvalidFullMoveClock(_) => write!(f, "Invalid full move clock"),
}
}
}

impl Error for ForsythEdwardsNotationError {}

impl From<PlacementError> for ForsythEdwardsNotationError {
fn from(value: PlacementError) -> Self {
Self::InvalidPlacements(value)
}
}

impl From<ActiveColorError> for ForsythEdwardsNotationError {
fn from(value: ActiveColorError) -> Self {
Self::InvalidActiveColor(value)
}
}

impl From<CastlingError> for ForsythEdwardsNotationError {
fn from(value: CastlingError) -> Self {
Self::InvalidCastling(value)
}
}

impl From<EnPassantError> for ForsythEdwardsNotationError {
fn from(value: EnPassantError) -> Self {
Self::InvalidEnPassant(value)
}
}

impl From<HalfMoveClockError> for ForsythEdwardsNotationError {
fn from(value: HalfMoveClockError) -> Self {
Self::InvalidHalfMoveClock(value)
}
}

impl From<FullMoveClockError> for ForsythEdwardsNotationError {
fn from(value: FullMoveClockError) -> Self {
Self::InvalidFullMoveClock(value)
}
}

impl TryFrom<&str> for ForsythEdwardsNotation {
type Error = ForsythEdwardsNotationError;

Expand All @@ -114,12 +168,12 @@ impl TryFrom<&str> for ForsythEdwardsNotation {
if parts.len() != FEN_PARTS {
return Err(Self::Error::Invalid);
}
let placements = Placements::try_from(parts[0]).map_err(Self::Error::InvalidPlacements)?;
let active_color = ActiveColor::try_from(parts[1]).map_err(Self::Error::InvalidActiveColor)?;
let castling = Castling::try_from(parts[2]).map_err(Self::Error::InvalidCastling)?;
let enpassant = EnPassant::try_from(parts[3]).map_err(Self::Error::InvalidEnPassant)?;
let half_move_clock = HalfMoveClock::try_from(parts[4]).map_err(Self::Error::InvalidHalfMoveClock)?;
let full_move_clock = FullMoveClock::try_from(parts[5]).map_err(Self::Error::InvalidFullMoveClock)?;
let placements = Placements::try_from(parts[0])?;
let active_color = ActiveColor::try_from(parts[1])?;
let castling = Castling::try_from(parts[2])?;
let enpassant = EnPassant::try_from(parts[3])?;
let half_move_clock = HalfMoveClock::try_from(parts[4])?;
let full_move_clock = FullMoveClock::try_from(parts[5])?;
let fen = Self::new(placements, active_color, castling, enpassant, half_move_clock, full_move_clock);
Ok(fen)
}
Expand Down
3 changes: 1 addition & 2 deletions libs/board/src/fen/placements.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::pieces::{PIECE_BYTES, PIECE_INDEX_LOOKUP_MAP};
use std::{
fmt::{Debug, Display},
str::Split,
};

use crate::pieces::{PIECE_BYTES, PIECE_INDEX_LOOKUP_MAP};

type Position = [[u8; NUM_FILES]; NUM_RANKS];

pub const NUM_RANKS: usize = 8;
Expand Down
39 changes: 27 additions & 12 deletions libs/board/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ use bitboard::{Bitboard, BitboardExt};
use fen::ForsythEdwardsNotation;
use pieces::{piece::Piece, Pieces, UTF_SYMBOLS};
use std::{
error::Error,
fmt::{Debug, Display},
mem::variant_count,
};

pub const BOARD_SIZE: i8 = 8;
pub const NORTH: i8 = BOARD_SIZE;
pub const BOARD_SIZE: u8 = 8;
pub const NORTH: i8 = BOARD_SIZE as i8;
pub const EAST: i8 = 1;
pub const SOUTH: i8 = -BOARD_SIZE;
pub const SOUTH: i8 = -(BOARD_SIZE as i8);
pub const WEST: i8 = -EAST;
pub const NORTH_EAST: i8 = NORTH + EAST;
pub const SOUTH_EAST: i8 = SOUTH + EAST;
Expand Down Expand Up @@ -88,10 +89,25 @@ pub struct Board {
pieces: Pieces,
}

#[derive(Debug)]
pub enum BoardError {
MissingPiece,
}

impl Display for BoardError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BoardError::MissingPiece => write!(f, "No piece found on source square"),
}
}
}

impl Error for BoardError {}

pub trait BoardExt {}

pub trait Verify {
fn verify(&self, source: Square, destination: Square, board: Board) -> Result<u16, ()>;
fn verify(&self, source: Square, destination: Square, promotion: Option<char>, board: Board) -> Result<u16, Box<dyn Error>>;
}

pub trait Shift {
Expand Down Expand Up @@ -190,19 +206,18 @@ impl Board {
&mut self.pieces
}

pub fn get_piece_index(&self, source: Square) -> Result<usize, ()> {
pub fn get_piece_index(&self, source: Square) -> Result<usize, Box<dyn Error>> {
let bitboard = Bitboard::from(source);
let pieces = self.pieces().get_all_pieces();
for (index, piece) in pieces.iter().enumerate() {
if Bitboard::overlap(bitboard, *piece) {
return Ok(index);
}
}
eprintln!("No piece found on {source}");
Err(())
Err(Box::new(BoardError::MissingPiece))
}

pub fn get_piece_mut(&mut self, source: Square) -> Result<Piece, ()> {
pub fn get_piece_mut(&mut self, source: Square) -> Result<Piece, Box<dyn Error>> {
let piece_index = self.get_piece_index(source).unwrap();
let pieces = self.pieces_mut();
match piece_index {
Expand All @@ -218,11 +233,11 @@ impl Board {
9 => Ok(Piece::from(pieces.white_pieces().queen())),
10 => Ok(Piece::from(pieces.white_pieces().king())),
11 => Ok(Piece::from(pieces.white_pieces().pawn())),
_ => Err(()),
_ => Err(Box::new(BoardError::MissingPiece)),
}
}

pub fn get_piece_board_mut(&mut self, source: Square) -> Result<&mut Bitboard, ()> {
pub fn get_piece_board_mut(&mut self, source: Square) -> Result<&mut Bitboard, Box<dyn Error>> {
let piece_index = self.get_piece_index(source).unwrap();
let pieces = self.pieces_mut();
match piece_index {
Expand All @@ -238,11 +253,11 @@ impl Board {
9 => Ok(pieces.white_pieces_mut().queen_mut().bitboard_mut()),
10 => Ok(pieces.white_pieces_mut().king_mut().bitboard_mut()),
11 => Ok(pieces.white_pieces_mut().pawn_mut().bitboard_mut()),
_ => Err(()),
_ => Err(Box::new(BoardError::MissingPiece)),
}
}

pub fn capture_piece(&mut self, square: Square) -> Result<(), ()> {
pub fn capture_piece(&mut self, square: Square) -> Result<(), Box<dyn Error>> {
let piece = self.get_piece_board_mut(square)?;
*piece ^= Bitboard::get_single_bit(square.into());
Ok(())
Expand Down
16 changes: 9 additions & 7 deletions libs/board/src/moves/irreversible/capture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::{
};
use api::Square;
use bitboard::{Bitboard, BitboardExt};
use std::fmt::{Debug, Display};
use std::{
error::Error,
fmt::{Debug, Display},
};

#[derive(Clone, Copy, PartialEq, Eq)]
pub struct CaptureMove {
Expand All @@ -26,15 +29,12 @@ impl CaptureMove {

pub trait CaptureMoveExt: IrreversibleMoveExt {}

impl CaptureMoveExt for CaptureMove {}
impl IrreversibleMoveExt for CaptureMove {}

impl MoveExt for CaptureMove {
fn coordinates(&self) -> Coordinates {
*self.coordinates()
}

fn march(&self, board: &mut Board) -> Result<(), ()> {
fn march(&self, board: &mut Board) -> Result<(), Box<dyn Error>> {
self.make(board)?;
let source = self.coordinates().source();
let destination = self.coordinates().destination();
Expand All @@ -44,8 +44,6 @@ impl MoveExt for CaptureMove {
}
}

impl Encode for CaptureMove {}

impl Display for CaptureMove {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let source = self.coordinates().source();
Expand All @@ -60,6 +58,10 @@ impl Debug for CaptureMove {
}
}

impl CaptureMoveExt for CaptureMove {}
impl IrreversibleMoveExt for CaptureMove {}
impl Encode for CaptureMove {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
18 changes: 10 additions & 8 deletions libs/board/src/moves/irreversible/castle/king.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::{

use super::CastleMoveExt;
use api::Square;
use std::fmt::{Debug, Display};
use std::{
error::Error,
fmt::{Debug, Display},
};

#[derive(Clone, Copy, PartialEq, Eq)]
pub struct KingCastleMove {
Expand All @@ -26,22 +29,16 @@ impl KingCastleMove {

pub trait KingCastleMoveExt: CastleMoveExt {}

impl KingCastleMoveExt for KingCastleMove {}
impl CastleMoveExt for KingCastleMove {}
impl IrreversibleMoveExt for KingCastleMove {}

impl MoveExt for KingCastleMove {
fn coordinates(&self) -> Coordinates {
*self.coordinates()
}

fn march(&self, board: &mut Board) -> Result<(), ()> {
fn march(&self, board: &mut Board) -> Result<(), Box<dyn Error>> {
self.castle(board)
}
}

impl Encode for KingCastleMove {}

impl Display for KingCastleMove {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let source = self.coordinates().source();
Expand All @@ -55,3 +52,8 @@ impl Debug for KingCastleMove {
Display::fmt(self, f)
}
}

impl KingCastleMoveExt for KingCastleMove {}
impl CastleMoveExt for KingCastleMove {}
impl IrreversibleMoveExt for KingCastleMove {}
impl Encode for KingCastleMove {}
13 changes: 8 additions & 5 deletions libs/board/src/moves/irreversible/castle/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub mod king;
pub mod queen;

use std::error::Error;

use super::IrreversibleMoveExt;
use crate::{
moves::{coordinates::Coordinates, MoveExt},
Expand All @@ -16,14 +18,11 @@ pub enum CastleMove {
}

pub trait CastleMoveExt: IrreversibleMoveExt {
fn castle(&self, board: &mut Board) -> Result<(), ()> {
fn castle(&self, board: &mut Board) -> Result<(), Box<dyn Error>> {
self.make(board)
}
}

impl CastleMoveExt for CastleMove {}
impl IrreversibleMoveExt for CastleMove {}

impl MoveExt for CastleMove {
fn coordinates(&self) -> Coordinates {
match *self {
Expand All @@ -32,10 +31,14 @@ impl MoveExt for CastleMove {
}
}

fn march(&self, board: &mut Board) -> Result<(), ()> {
fn march(&self, board: &mut Board) -> Result<(), Box<dyn Error>> {
match *self {
CastleMove::King(king) => king.march(board),
CastleMove::Queen(queen) => queen.march(board),
}
}
}

impl CastleMoveExt for CastleMove {}

impl IrreversibleMoveExt for CastleMove {}
Loading

0 comments on commit 6bf7279

Please sign in to comment.