use std::slice;
use std::ops::{Deref,DerefMut,Index,IndexMut};
use std::iter::{Iterator,IntoIterator,FusedIterator,ExactSizeIterator,FromIterator};
#[cfg(feature = "nightly")]
use std::iter::TrustedLen;
use super::piece_move::{BitMove, ScoringMove};
pub trait MVPushable: Sized + IndexMut<usize> + Index<usize> + DerefMut {
fn push_mv(&mut self, mv: BitMove);
unsafe fn unchecked_push_mv(&mut self, mv: BitMove);
unsafe fn unchecked_set_len(&mut self, len: usize);
unsafe fn list_ptr(&mut self) -> *mut Self::Output;
unsafe fn over_bounds_ptr(&mut self) -> *mut Self::Output;
}
#[cfg(target_pointer_width = "128")]
pub const MAX_MOVES: usize = 248;
#[cfg(target_pointer_width = "64")]
pub const MAX_MOVES: usize = 252;
#[cfg(target_pointer_width = "32")]
pub const MAX_MOVES: usize = 254;
#[cfg(any(
target_pointer_width = "16",
target_pointer_width = "8",
))]
pub const MAX_MOVES: usize = 255;
pub struct MoveList {
inner: [BitMove; MAX_MOVES],
len: usize,
}
impl Default for MoveList {
#[inline]
fn default() -> Self {
MoveList {
inner: [BitMove::null(); MAX_MOVES],
len: 0,
}
}
}
impl From<Vec<BitMove>> for MoveList {
fn from(vec: Vec<BitMove>) -> Self {
let mut list = MoveList::default();
vec.iter().for_each(|m| list.push(*m));
list
}
}
impl From<ScoringMoveList> for MoveList {
fn from(sc_list: ScoringMoveList) -> Self {
let mut mv_list = MoveList::default();
sc_list.iter().for_each(|m| mv_list.push(m.bitmove()));
mv_list
}
}
impl Into<Vec<BitMove>> for MoveList {
#[inline]
fn into(self) -> Vec<BitMove> {
self.vec()
}
}
impl MoveList {
#[inline(always)]
pub fn push(&mut self, mv: BitMove) {
self.push_mv(mv);
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn vec(&self) -> Vec<BitMove> {
let mut vec = Vec::with_capacity(self.len);
for mov in self.iter() {
vec.push(*mov);
}
assert_eq!(vec.len(),self.len);
vec
}
#[inline(always)]
pub fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub fn as_slice(&self) -> &[BitMove] {
self
}
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [BitMove] {
self
}
}
impl Deref for MoveList {
type Target = [BitMove];
#[inline]
fn deref(&self) -> &[BitMove] {
unsafe {
let p = self.inner.as_ptr();
slice::from_raw_parts(p, self.len)
}
}
}
impl DerefMut for MoveList {
#[inline]
fn deref_mut(&mut self) -> &mut [BitMove] {
unsafe {
let ptr = self.inner.as_mut_ptr();
slice::from_raw_parts_mut(ptr, self.len)
}
}
}
impl Index<usize> for MoveList {
type Output = BitMove;
#[inline(always)]
fn index(&self, index: usize) -> &BitMove {
&(**self)[index]
}
}
impl IndexMut<usize> for MoveList {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut BitMove {
&mut (**self)[index]
}
}
impl MVPushable for MoveList {
#[inline(always)]
fn push_mv(&mut self, mv: BitMove) {
if self.len() < MAX_MOVES {
unsafe{ self.unchecked_push_mv(mv) }
}
}
#[inline(always)]
unsafe fn unchecked_push_mv(&mut self, mv: BitMove) {
let end = self.inner.get_unchecked_mut(self.len);
*end = mv;
self.len += 1;
}
#[inline(always)]
unsafe fn unchecked_set_len(&mut self, len: usize) {
self.len = len
}
#[inline(always)]
unsafe fn list_ptr(&mut self) -> *mut BitMove {
self.as_mut_ptr()
}
#[inline(always)]
unsafe fn over_bounds_ptr(&mut self) -> *mut BitMove {
self.as_mut_ptr().add(self.len)
}
}
pub struct MoveIter<'a> {
movelist: &'a MoveList,
idx: usize
}
impl<'a> Iterator for MoveIter<'a> {
type Item = BitMove;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.movelist.len {
None
} else {
unsafe {
let m = *self.movelist.inner.get_unchecked(self.idx);
self.idx += 1;
Some(m)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.movelist.len - self.idx, Some(self.movelist.len - self.idx))
}
}
impl<'a> IntoIterator for &'a MoveList {
type Item = BitMove;
type IntoIter = MoveIter<'a>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
MoveIter {
movelist: self,
idx: 0,
}
}
}
impl<'a> ExactSizeIterator for MoveIter<'a> {}
impl<'a> FusedIterator for MoveIter<'a> {}
#[cfg(feature = "nightly")]
unsafe impl<'a> TrustedLen for MoveIter<'a> {}
pub struct MoveIntoIter {
movelist: MoveList,
idx: usize
}
impl Iterator for MoveIntoIter {
type Item = BitMove;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.movelist.len {
None
} else {
unsafe {
let m = *self.movelist.inner.get_unchecked(self.idx);
self.idx += 1;
Some(m)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.movelist.len - self.idx, Some(self.movelist.len - self.idx))
}
}
impl IntoIterator for MoveList {
type Item = BitMove;
type IntoIter = MoveIntoIter;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
MoveIntoIter {
movelist: self,
idx: 0,
}
}
}
impl FromIterator<BitMove> for MoveList {
fn from_iter<T: IntoIterator<Item=BitMove>>(iter: T) -> Self {
let mut list = MoveList::default();
for i in iter {
list.push(i);
}
list
}
}
impl ExactSizeIterator for MoveIntoIter {}
impl FusedIterator for MoveIntoIter {}
#[cfg(feature = "nightly")]
unsafe impl TrustedLen for MoveIntoIter {}
pub struct ScoringMoveList {
inner: [ScoringMove; MAX_MOVES],
len: usize,
}
impl Default for ScoringMoveList {
#[inline]
fn default() -> Self {
ScoringMoveList {
inner: [ScoringMove::default(); MAX_MOVES],
len: 0,
}
}
}
impl From<Vec<BitMove>> for ScoringMoveList {
fn from(vec: Vec<BitMove>) -> Self {
let mut list = ScoringMoveList::default();
vec.iter().for_each(|m| list.push(*m));
list
}
}
impl From<MoveList> for ScoringMoveList {
fn from(mv_list: MoveList) -> Self {
let mut sc_list = ScoringMoveList::default();
mv_list.iter().for_each(|m| sc_list.push(*m));
sc_list
}
}
impl Into<Vec<ScoringMove>> for ScoringMoveList {
#[inline]
fn into(self) -> Vec<ScoringMove> {
self.vec()
}
}
impl ScoringMoveList {
#[inline(always)]
pub fn push(&mut self, mov: BitMove) {
self.push_mv(mov)
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn vec(&self) -> Vec<ScoringMove> {
let mut vec = Vec::with_capacity(self.len);
for pair in self.iter() {
vec.push(*pair);
}
assert_eq!(vec.len(),self.len);
vec
}
#[inline(always)]
pub fn push_score(&mut self, mov: BitMove, score: i16) {
if self.len < MAX_MOVES {
unsafe {
self.push_score_unchecked(mov, score);
}
}
}
#[inline(always)]
pub unsafe fn push_score_unchecked(&mut self, mov: BitMove, score: i16) {
let end = self.inner.get_unchecked_mut(self.len);
*end = ScoringMove::new_score(mov, score);
self.len += 1;
}
#[inline(always)]
pub fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub fn as_slice(&self) -> &[ScoringMove] {
self
}
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [ScoringMove] {
self
}
}
impl Deref for ScoringMoveList {
type Target = [ScoringMove];
#[inline]
fn deref(&self) -> &[ScoringMove] {
unsafe {
let p = self.inner.as_ptr();
slice::from_raw_parts(p, self.len)
}
}
}
impl DerefMut for ScoringMoveList {
#[inline]
fn deref_mut(&mut self) -> &mut [ScoringMove] {
unsafe {
let ptr = self.inner.as_mut_ptr();
slice::from_raw_parts_mut(ptr, self.len)
}
}
}
impl Index<usize> for ScoringMoveList {
type Output = ScoringMove;
#[inline(always)]
fn index(&self, index: usize) -> &ScoringMove {
&(**self)[index]
}
}
impl IndexMut<usize> for ScoringMoveList {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut ScoringMove {
&mut (**self)[index]
}
}
impl MVPushable for ScoringMoveList {
#[inline(always)]
fn push_mv(&mut self, mv: BitMove) {
if self.len() < MAX_MOVES {
unsafe{ self.unchecked_push_mv(mv) }
}
}
#[inline(always)]
unsafe fn unchecked_push_mv(&mut self, mv: BitMove) {
let end = self.inner.get_unchecked_mut(self.len);
*end = ScoringMove::new(mv);
self.len += 1;
}
#[inline(always)]
unsafe fn unchecked_set_len(&mut self, len: usize) {
self.len = len
}
#[inline(always)]
unsafe fn list_ptr(&mut self) -> *mut ScoringMove {
self.as_mut_ptr()
}
#[inline(always)]
unsafe fn over_bounds_ptr(&mut self) -> *mut ScoringMove {
self.as_mut_ptr().add(self.len)
}
}
pub struct ScoreMoveIter<'a> {
movelist: &'a ScoringMoveList,
idx: usize
}
impl<'a> Iterator for ScoreMoveIter<'a> {
type Item = ScoringMove;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.movelist.len {
None
} else {
unsafe {
let m = *self.movelist.inner.get_unchecked(self.idx);
self.idx += 1;
Some(m)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.movelist.len - self.idx, Some(self.movelist.len - self.idx))
}
}
impl<'a> IntoIterator for &'a ScoringMoveList {
type Item = ScoringMove;
type IntoIter = ScoreMoveIter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
ScoreMoveIter {
movelist: self,
idx: 0,
}
}
}
impl<'a> ExactSizeIterator for ScoreMoveIter<'a> {}
impl<'a> FusedIterator for ScoreMoveIter<'a> {}
#[cfg(feature = "nightly")]
unsafe impl<'a> TrustedLen for ScoreMoveIter<'a> {}
pub struct ScoreMoveIntoIter {
movelist: ScoringMoveList,
idx: usize
}
impl Iterator for ScoreMoveIntoIter {
type Item = ScoringMove;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.movelist.len {
None
} else {
unsafe {
let m = *self.movelist.inner.get_unchecked(self.idx);
self.idx += 1;
Some(m)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.movelist.len - self.idx, Some(self.movelist.len - self.idx))
}
}
impl IntoIterator for ScoringMoveList {
type Item = ScoringMove;
type IntoIter = ScoreMoveIntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
ScoreMoveIntoIter {
movelist: self,
idx: 0,
}
}
}
impl FromIterator<BitMove> for ScoringMoveList {
fn from_iter<T: IntoIterator<Item=BitMove>>(iter: T) -> Self {
let mut list = ScoringMoveList::default();
for i in iter {
list.push(i);
}
list
}
}
impl ExactSizeIterator for ScoreMoveIntoIter {}
impl FusedIterator for ScoreMoveIntoIter {}
#[cfg(feature = "nightly")]
unsafe impl TrustedLen for ScoreMoveIntoIter {}