Skip to content

Commit

Permalink
use options and ArrayVec
Browse files Browse the repository at this point in the history
  • Loading branch information
Heiaha committed Nov 18, 2024
1 parent 6264882 commit 9d5c4a5
Show file tree
Hide file tree
Showing 15 changed files with 341 additions and 371 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ edition = "2021"
readme = "README.md"
rust-version = "1.63"

[dependencies]
arrayvec = "0.7.6"

[profile.release]
opt-level = 3
debug = false
Expand Down
2 changes: 1 addition & 1 deletion src/bitboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ impl fmt::Debug for Bitboard {
let mut result = String::new();
for i in (0..=56).rev().step_by(8) {
for j in 0..8 {
result.push_str(format!("{} ", self.0 >> (i + j) & 1).as_ref());
result.push_str(format!("{} ", self.0 >> (i + j) & 1).as_str());
}
result.push('\n');
}
Expand Down
285 changes: 116 additions & 169 deletions src/board.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![expect(static_mut_refs)]
#![allow(dead_code)]
#![allow(non_snake_case)] // Allow so we don't get a warning about the uppercase name.

Expand Down
38 changes: 17 additions & 21 deletions src/moov.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ impl Move {
MoveFlags::from(((self.0 >> 12) & 0xf) as u8)
}

pub fn move_int(&self) -> MoveInt {
self.0
}

pub fn is_quiet(&self) -> bool {
(self.0 >> 12) & 0b1100 == 0
}
Expand All @@ -36,23 +40,19 @@ impl Move {
self.flags() == MoveFlags::EnPassant
}

pub fn promotion(&self) -> PieceType {
pub fn promotion(&self) -> Option<PieceType> {
match self.flags() {
MoveFlags::PrKnight | MoveFlags::PcKnight => PieceType::Knight,
MoveFlags::PrBishop | MoveFlags::PcBishop => PieceType::Bishop,
MoveFlags::PrRook | MoveFlags::PcRook => PieceType::Rook,
MoveFlags::PrQueen | MoveFlags::PcQueen => PieceType::Queen,
_ => PieceType::None,
MoveFlags::PrKnight | MoveFlags::PcKnight => Some(PieceType::Knight),
MoveFlags::PrBishop | MoveFlags::PcBishop => Some(PieceType::Bishop),
MoveFlags::PrRook | MoveFlags::PcRook => Some(PieceType::Rook),
MoveFlags::PrQueen | MoveFlags::PcQueen => Some(PieceType::Queen),
_ => None,
}
}

pub fn is_castling(&self) -> bool {
matches!(self.flags(), MoveFlags::OO | MoveFlags::OOO)
}

pub fn is_null(&self) -> bool {
*self == Move::NULL
}
}

impl From<MoveInt> for Move {
Expand All @@ -63,12 +63,14 @@ impl From<MoveInt> for Move {

impl fmt::Display for Move {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}{}", self.from_sq(), self.to_sq(), self.promotion())
}
}
write!(f, "{}{}", self.from_sq(), self.to_sq())?;

impl Move {
pub const NULL: Self = Self(0);
if let Some(promotion_pt) = self.promotion() {
write!(f, "{}", promotion_pt)?;
}

Ok(())
}
}

#[derive(Debug, PartialEq, Eq)]
Expand All @@ -89,12 +91,6 @@ pub enum MoveFlags {
PcQueen = 0b1111,
}

impl Default for MoveFlags {
fn default() -> Self {
MoveFlags::Quiet
}
}

impl From<u8> for MoveFlags {
fn from(n: u8) -> Self {
unsafe { std::mem::transmute::<u8, Self>(n) }
Expand Down
123 changes: 61 additions & 62 deletions src/move_list.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
use std::fmt;
use std::ops::Index;

use super::bitboard::*;
use super::board::*;
use super::moov::*;
use super::square::*;
use super::types::*;

use arrayvec::ArrayVec;

// Cache size consideration idea originally found in Pleco

// Make sure the move lists are aligned into lengths such that the memory is
// in an integer number of cache chunks. The is for a 16 bit Move.
// in an integer number of cache chunks. The is for a 32 bit Move.
// https://www.youtube.com/watch?v=WDIkqP4JbkE

#[cfg(target_pointer_width = "64")]
Expand All @@ -20,21 +19,22 @@ const MAX_MOVES: usize = 254;
#[cfg(any(target_pointer_width = "16"))]
const MAX_MOVES: usize = 255;

pub struct MoveList {
moves: [Move; MAX_MOVES],
pub scores: [Value; MAX_MOVES],
idx: usize,
len: usize,
pub struct MoveListEntry {
pub m: Move,
pub score: Value,
}

pub struct MoveList(ArrayVec<MoveListEntry, MAX_MOVES>);

impl MoveListEntry {
pub fn new(m: Move) -> Self {
MoveListEntry { m, score: 0 }
}
}

impl MoveList {
pub fn new() -> Self {
Self {
moves: [Move::NULL; MAX_MOVES],
scores: [0; MAX_MOVES],
idx: 0,
len: 0,
}
Self(ArrayVec::new())
}

pub fn from(board: &Board) -> Self {
Expand All @@ -50,36 +50,44 @@ impl MoveList {
}

pub fn len(&self) -> usize {
self.len
self.0.len()
}

pub fn contains(&self, m: Move) -> bool {
self.moves[..self.len].contains(&m)
pub fn push(&mut self, m: Move) {
self.0.push(MoveListEntry::new(m));
}

pub fn push(&mut self, m: Move) {
self.moves[self.len] = m;
self.len += 1;
pub fn contains(&self, m: Move) -> bool {
self.0.iter().any(|entry| entry.m == m)
}

pub fn make_q(&mut self, from_sq: SQ, to: Bitboard) {
for to_sq in to {
self.moves[self.len] = Move::new(from_sq, to_sq, MoveFlags::Quiet);
self.len += 1;
self.0.push(MoveListEntry::new(Move::new(
from_sq,
to_sq,
MoveFlags::Quiet,
)));
}
}

pub fn make_c(&mut self, from_sq: SQ, to: Bitboard) {
for to_sq in to {
self.moves[self.len] = Move::new(from_sq, to_sq, MoveFlags::Capture);
self.len += 1;
self.0.push(MoveListEntry::new(Move::new(
from_sq,
to_sq,
MoveFlags::Capture,
)));
}
}

pub fn make_dp(&mut self, from_sq: SQ, to: Bitboard) {
for to_sq in to {
self.moves[self.len] = Move::new(from_sq, to_sq, MoveFlags::DoublePush);
self.len += 1;
self.0.push(MoveListEntry::new(Move::new(
from_sq,
to_sq,
MoveFlags::DoublePush,
)));
}
}

Expand All @@ -91,64 +99,55 @@ impl MoveList {
MoveFlags::PcRook,
MoveFlags::PcBishop,
] {
self.moves[self.len] = Move::new(from_sq, to_sq, flag);
self.len += 1;
self.0
.push(MoveListEntry::new(Move::new(from_sq, to_sq, flag)));
}
}
}

pub fn next_best(&mut self) -> Option<Move> {
if self.idx == self.len {
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut MoveListEntry> {
self.0.iter_mut()
}

pub fn iter_moves<'a>(&'a self) -> impl Iterator<Item = Move> + 'a {
self.0.iter().map(|entry| entry.m)
}

pub fn next_best(&mut self, idx: usize) -> Option<Move> {
if idx == self.len() {
return None;
}

let mut max_score = Value::MIN;
let mut max_idx = self.idx;
let mut max_idx = idx;

for i in self.idx..self.len() {
if self.scores[i] > max_score {
for i in idx..self.len() {
if self.0[i].score > max_score {
max_idx = i;
max_score = self.scores[i];
max_score = self.0[i].score;
}
}

self.moves.swap(self.idx, max_idx);
self.scores.swap(self.idx, max_idx);

let idx = self.idx;
self.idx += 1;
Some(self.moves[idx])
}
}

impl Iterator for MoveList {
type Item = Move;

fn next(&mut self) -> Option<Self::Item> {
if self.idx == self.len {
self.idx = 0;
return None;
}
self.0.swap(idx, max_idx);

let idx = self.idx;
self.idx += 1;
Some(self.moves[idx])
Some(self.0[idx].m)
}
}

impl Index<usize> for MoveList {
type Output = Move;
impl std::ops::Index<usize> for MoveList {
type Output = MoveListEntry;

fn index(&self, i: usize) -> &Self::Output {
&self.moves[i]
&self.0[i]
}
}

impl fmt::Debug for MoveList {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl std::fmt::Debug for MoveList {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut result = String::from('[');
for i in 0..self.len {
result.push_str(format!("{}, ", self.moves[i]).as_ref());
for i in 0..self.len() {
let m = self.0[i].m;
result.push_str(format!("{}, ", m).as_str());
}
result.push(']');
write!(f, "{}", result)
Expand Down
Loading

0 comments on commit 9d5c4a5

Please sign in to comment.