place weighting
This commit is contained in:
parent
e1d83825b7
commit
d29095bc9d
33
Cargo.lock
generated
33
Cargo.lock
generated
@ -129,6 +129,17 @@ version = "0.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "comptime"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed5e683f1f8879ac923fa7f69d180872f9bb8a417505c332f08fa6955f537dd2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
version = "0.15.10"
|
version = "0.15.10"
|
||||||
@ -431,6 +442,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bitvec",
|
"bitvec",
|
||||||
|
"comptime",
|
||||||
"const_fn",
|
"const_fn",
|
||||||
"criterion",
|
"criterion",
|
||||||
"either",
|
"either",
|
||||||
@ -626,7 +638,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.98",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -647,6 +659,17 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.98"
|
version = "2.0.98"
|
||||||
@ -727,7 +750,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.98",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -749,7 +772,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.98",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@ -910,7 +933,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.98",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -921,5 +944,5 @@ checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.98",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -29,6 +29,7 @@ bitvec = [ "dep:bitvec" ]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
arrayvec = "0.7"
|
arrayvec = "0.7"
|
||||||
bitvec = { version = "1", optional = true }
|
bitvec = { version = "1", optional = true }
|
||||||
|
comptime = "1.0.0"
|
||||||
const_fn = "0.4.11"
|
const_fn = "0.4.11"
|
||||||
either = "1.13"
|
either = "1.13"
|
||||||
indicatif = "0.17"
|
indicatif = "0.17"
|
||||||
|
|||||||
@ -15,7 +15,7 @@ impl ComplexAgent {
|
|||||||
const MAX_DEPTH: usize = 12;
|
const MAX_DEPTH: usize = 12;
|
||||||
Self {
|
Self {
|
||||||
color,
|
color,
|
||||||
future_moves: FutureMoves::new(color, MAX_DEPTH, 4),
|
future_moves: FutureMoves::new(color, MAX_DEPTH, 6),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use crate::repr::{Board, Piece, PosMap};
|
use crate::repr::{Board, Piece, PosMap};
|
||||||
|
|
||||||
pub struct BoardValueMap(PosMap<i8>);
|
pub struct BoardValueMap(PosMap<i64>);
|
||||||
|
|
||||||
impl BoardValueMap {
|
impl BoardValueMap {
|
||||||
pub fn board_value(&self, board: &Board, color: Piece) -> i8 {
|
pub fn board_value(&self, board: &Board, color: Piece) -> i64 {
|
||||||
Board::all_positions()
|
Board::all_positions()
|
||||||
.filter_map(|(i, j)| board.get(i, j).map(|p| (i, j, p)))
|
.filter_map(|(i, j)| board.get(i, j).map(|p| (i, j, p)))
|
||||||
.map(|(i, j, pos_p)| {
|
.map(|(i, j, pos_p)| {
|
||||||
@ -25,7 +25,11 @@ impl BoardValueMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i, j) in Board::sides() {
|
for (i, j) in Board::sides() {
|
||||||
map.set(i, j, 4);
|
map.set(i, j, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, j) in Board::corners() {
|
||||||
|
map.set(i, j, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self(map)
|
Self(map)
|
||||||
|
|||||||
@ -55,6 +55,6 @@ impl Move {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BVM.board_value(&self.board, agent_color) as i64
|
BVM.board_value(&self.board, agent_color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,8 +10,8 @@ pub mod repr;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let player1 = complexagent::ComplexAgent::new(Piece::Black);
|
let player1 = complexagent::ComplexAgent::new(Piece::Black);
|
||||||
// let player2 = complexagent::ComplexAgent::new(Piece::White);
|
// let player2 = complexagent::ComplexAgent::new(Piece::White);
|
||||||
let player2 = agent::ManualAgent::new(Piece::White);
|
// let player2 = agent::ManualAgent::new(Piece::White);
|
||||||
// let player2 = agent::RandomAgent::new(Piece::White);
|
let player2 = agent::RandomAgent::new(Piece::White);
|
||||||
let mut game = Game::new(Box::new(player1), Box::new(player2));
|
let mut game = Game::new(Box::new(player1), Box::new(player2));
|
||||||
game.game_loop();
|
game.game_loop();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::repr::board::{BOARD_AREA, BOARD_SIZE};
|
use crate::repr::board::Board;
|
||||||
use const_fn::const_fn;
|
use const_fn::const_fn;
|
||||||
use static_assertions::const_assert;
|
use static_assertions::const_assert;
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ use bitvec::prelude::*;
|
|||||||
type BBBaseType = u64;
|
type BBBaseType = u64;
|
||||||
|
|
||||||
#[cfg(feature = "bitvec")]
|
#[cfg(feature = "bitvec")]
|
||||||
pub type BitBoardInner = BitArr!(for BOARD_AREA, in BBBaseType, Lsb0);
|
pub type BitBoardInner = BitArr!(for Board::BOARD_AREA, in BBBaseType, Lsb0);
|
||||||
|
|
||||||
#[cfg(not(feature = "bitvec"))]
|
#[cfg(not(feature = "bitvec"))]
|
||||||
pub type BitBoardInner = u64;
|
pub type BitBoardInner = u64;
|
||||||
@ -24,7 +24,7 @@ pub type BitBoardInner = u64;
|
|||||||
pub struct BitBoard(BitBoardInner);
|
pub struct BitBoard(BitBoardInner);
|
||||||
|
|
||||||
// BitBoard should be big enough to fit all points on the board
|
// BitBoard should be big enough to fit all points on the board
|
||||||
const_assert!(std::mem::size_of::<BitBoard>() * 8 >= BOARD_AREA);
|
const_assert!(std::mem::size_of::<BitBoard>() * 8 >= Board::BOARD_AREA);
|
||||||
|
|
||||||
impl Default for BitBoard {
|
impl Default for BitBoard {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@ -35,7 +35,7 @@ impl Default for BitBoard {
|
|||||||
impl BitBoard {
|
impl BitBoard {
|
||||||
#[cfg(feature = "bitvec")]
|
#[cfg(feature = "bitvec")]
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self(bitarr!(BBBaseType, Lsb0; 0; BOARD_AREA))
|
Self(bitarr!(BBBaseType, Lsb0; 0; Board::BOARD_AREA))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "bitvec"))]
|
#[cfg(not(feature = "bitvec"))]
|
||||||
@ -57,7 +57,7 @@ impl BitBoard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fn get_index(row: usize, col: usize) -> usize {
|
const fn get_index(row: usize, col: usize) -> usize {
|
||||||
row * BOARD_SIZE + col
|
row * Board::BOARD_SIZE + col
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "bitvec")]
|
#[cfg(feature = "bitvec")]
|
||||||
@ -84,8 +84,8 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn set_and_get() {
|
fn set_and_get() {
|
||||||
let mut b = BitBoard::new();
|
let mut b = BitBoard::new();
|
||||||
for i in 0..BOARD_SIZE {
|
for i in 0..Board::BOARD_SIZE {
|
||||||
for j in 0..BOARD_SIZE {
|
for j in 0..Board::BOARD_SIZE {
|
||||||
assert!(
|
assert!(
|
||||||
!b.get(i, j),
|
!b.get(i, j),
|
||||||
"A just-initalized BitBoard should be completely empty"
|
"A just-initalized BitBoard should be completely empty"
|
||||||
|
|||||||
@ -8,34 +8,33 @@ use const_fn::const_fn;
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::{cmp::Ordering, collections::HashSet, fmt};
|
use std::{cmp::Ordering, collections::HashSet, fmt};
|
||||||
|
|
||||||
/// Size of each dim of the board
|
|
||||||
pub const BOARD_SIZE: usize = 8;
|
|
||||||
|
|
||||||
/// Area of the board
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub const BOARD_AREA: usize = BOARD_SIZE * BOARD_SIZE;
|
|
||||||
|
|
||||||
const BOARD_SIZE_N1: usize = BOARD_SIZE - 1;
|
|
||||||
|
|
||||||
/// A chain of positions across the board
|
/// A chain of positions across the board
|
||||||
type Chain = ArrayVec<(usize, usize), BOARD_SIZE_N1>;
|
type Chain = ArrayVec<(usize, usize), { Board::BOARD_SIZE - 1 }>;
|
||||||
|
|
||||||
/// A collection of chains (up vert, down vert, left horiz, right horiz, diagonals....)
|
/// A collection of chains (up vert, down vert, left horiz, right horiz, diagonals....)
|
||||||
type ChainCollection = ArrayVec<Chain, 8>;
|
type ChainCollection = ArrayVec<Chain, 8>;
|
||||||
|
|
||||||
|
const BOARD_AREA: usize = Board::BOARD_AREA;
|
||||||
|
|
||||||
/// Map of all points on the board against some type T
|
/// Map of all points on the board against some type T
|
||||||
/// Used to index like so: example[i][j]
|
/// Used to index like so: example[i][j]
|
||||||
/// with each coordinate
|
/// with each coordinate
|
||||||
pub struct PosMap<T: Default>(ArrayVec<T, BOARD_AREA>);
|
pub struct PosMap<T: Default>(ArrayVec<T, BOARD_AREA>);
|
||||||
|
|
||||||
|
impl<T: Default> Default for PosMap<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Default> PosMap<T> {
|
impl<T: Default> PosMap<T> {
|
||||||
const fn index(row: usize, col: usize) -> usize {
|
const fn index(row: usize, col: usize) -> usize {
|
||||||
row * BOARD_SIZE + col
|
row * Board::BOARD_SIZE + col
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(ArrayVec::from_iter(
|
Self(ArrayVec::from_iter(
|
||||||
(0..BOARD_AREA).map(|_| Default::default()),
|
(0..Board::BOARD_AREA).map(|_| Default::default()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ impl<T: Default> PosMap<T> {
|
|||||||
let index = Self::index(row, col);
|
let index = Self::index(row, col);
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
BOARD_AREA + 1 >= index,
|
Board::BOARD_AREA + 1 >= index,
|
||||||
"index out of range, was: {}",
|
"index out of range, was: {}",
|
||||||
index
|
index
|
||||||
);
|
);
|
||||||
@ -54,7 +53,7 @@ impl<T: Default> PosMap<T> {
|
|||||||
pub fn set(&mut self, row: usize, col: usize, value: T) {
|
pub fn set(&mut self, row: usize, col: usize, value: T) {
|
||||||
let index = Self::index(row, col);
|
let index = Self::index(row, col);
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
BOARD_AREA + 1 >= index,
|
Board::BOARD_AREA + 1 >= index,
|
||||||
"index out of range, was: {}",
|
"index out of range, was: {}",
|
||||||
index
|
index
|
||||||
);
|
);
|
||||||
@ -69,8 +68,8 @@ fn gen_adj_lookup() -> PosMap<ChainCollection> {
|
|||||||
Board::all_positions()
|
Board::all_positions()
|
||||||
.map(|(i, j)| {
|
.map(|(i, j)| {
|
||||||
let (i_chain, j_chain) = (
|
let (i_chain, j_chain) = (
|
||||||
split_from(0..=BOARD_SIZE - 1, i),
|
split_from(0..=Board::BOARD_SIZE - 1, i),
|
||||||
split_from(0..=BOARD_SIZE - 1, j),
|
split_from(0..=Board::BOARD_SIZE - 1, j),
|
||||||
);
|
);
|
||||||
|
|
||||||
let chains: ChainCollection = ArrayVec::from_iter(
|
let chains: ChainCollection = ArrayVec::from_iter(
|
||||||
@ -95,7 +94,7 @@ fn gen_adj_lookup() -> PosMap<ChainCollection> {
|
|||||||
.iter()
|
.iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.flat_map(|(i, j)| [i, j]) // flatten to just numbers
|
.flat_map(|(i, j)| [i, j]) // flatten to just numbers
|
||||||
.all(|x| (0..BOARD_SIZE).contains(x)),
|
.all(|x| (0..Board::BOARD_SIZE).contains(x)),
|
||||||
"chains go out-of-bounds"
|
"chains go out-of-bounds"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -138,25 +137,25 @@ pub struct Board {
|
|||||||
impl fmt::Display for Board {
|
impl fmt::Display for Board {
|
||||||
#[allow(clippy::repeat_once)] // clippy gets mad about when PADDING == 1
|
#[allow(clippy::repeat_once)] // clippy gets mad about when PADDING == 1
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let horiz_sep_line = "-".repeat(BOARD_SIZE * 2 + 1);
|
let horiz_sep_line = "-".repeat(Self::BOARD_SIZE * 2 + 1);
|
||||||
|
|
||||||
// basically calculates the # of digits BOARD_SIZE needs
|
// basically calculates the # of digits BOARD_SIZE needs
|
||||||
const PADDING: usize = (BOARD_SIZE - 1).ilog10() as usize + 1;
|
const PADDING: usize = (Board::BOARD_SIZE - 1).ilog10() as usize + 1;
|
||||||
|
|
||||||
let space_padding = " ".repeat(PADDING);
|
let space_padding = " ".repeat(PADDING);
|
||||||
|
|
||||||
// Print numbers at top so the board can be read more easier
|
// Print numbers at top so the board can be read more easier
|
||||||
write!(f, "{} ", space_padding)?;
|
write!(f, "{} ", space_padding)?;
|
||||||
for j in (0..BOARD_SIZE).rev() {
|
for j in (0..Self::BOARD_SIZE).rev() {
|
||||||
write!(f, "{:0PADDING$} ", j)?;
|
write!(f, "{:0PADDING$} ", j)?;
|
||||||
}
|
}
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
|
|
||||||
for i in (0..BOARD_SIZE).rev() {
|
for i in (0..Self::BOARD_SIZE).rev() {
|
||||||
writeln!(f, "{}{}", space_padding, horiz_sep_line)?;
|
writeln!(f, "{}{}", space_padding, horiz_sep_line)?;
|
||||||
|
|
||||||
write!(f, "{:0PADDING$}|", i)?;
|
write!(f, "{:0PADDING$}|", i)?;
|
||||||
for j in (0..BOARD_SIZE).rev() {
|
for j in (0..Self::BOARD_SIZE).rev() {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}|",
|
"{}|",
|
||||||
@ -194,6 +193,11 @@ impl Default for Board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
|
pub const BOARD_SIZE: usize = 8;
|
||||||
|
|
||||||
|
/// Area of the board
|
||||||
|
pub const BOARD_AREA: usize = Self::BOARD_SIZE.pow(2);
|
||||||
|
|
||||||
/// Create a new empty board
|
/// Create a new empty board
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -205,16 +209,28 @@ impl Board {
|
|||||||
/// Starting position
|
/// Starting position
|
||||||
#[const_fn(cfg(not(feature = "bitvec")))]
|
#[const_fn(cfg(not(feature = "bitvec")))]
|
||||||
pub const fn starting_pos(mut self) -> Self {
|
pub const fn starting_pos(mut self) -> Self {
|
||||||
self.place_unchecked((BOARD_SIZE / 2) - 1, (BOARD_SIZE / 2) - 1, Piece::White);
|
self.place_unchecked(
|
||||||
self.place_unchecked(BOARD_SIZE / 2, (BOARD_SIZE / 2) - 1, Piece::Black);
|
(Self::BOARD_SIZE / 2) - 1,
|
||||||
self.place_unchecked((BOARD_SIZE / 2) - 1, BOARD_SIZE / 2, Piece::Black);
|
(Self::BOARD_SIZE / 2) - 1,
|
||||||
self.place_unchecked(BOARD_SIZE / 2, BOARD_SIZE / 2, Piece::White);
|
Piece::White,
|
||||||
|
);
|
||||||
|
self.place_unchecked(
|
||||||
|
Self::BOARD_SIZE / 2,
|
||||||
|
(Self::BOARD_SIZE / 2) - 1,
|
||||||
|
Piece::Black,
|
||||||
|
);
|
||||||
|
self.place_unchecked(
|
||||||
|
(Self::BOARD_SIZE / 2) - 1,
|
||||||
|
Self::BOARD_SIZE / 2,
|
||||||
|
Piece::Black,
|
||||||
|
);
|
||||||
|
self.place_unchecked(Self::BOARD_SIZE / 2, Self::BOARD_SIZE / 2, Piece::White);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides an iterator of all possible positions on the board
|
/// Provides an iterator of all possible positions on the board
|
||||||
pub fn all_positions() -> impl Iterator<Item = (usize, usize)> {
|
pub fn all_positions() -> impl Iterator<Item = (usize, usize)> {
|
||||||
(0..BOARD_SIZE).flat_map(|i| (0..BOARD_SIZE).map(move |j| (i, j)))
|
(0..Self::BOARD_SIZE).flat_map(|i| (0..Self::BOARD_SIZE).map(move |j| (i, j)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator of all possible moves a `color` can make
|
/// Returns an iterator of all possible moves a `color` can make
|
||||||
@ -223,11 +239,17 @@ impl Board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn sides() -> impl Iterator<Item = (usize, usize)> {
|
pub fn sides() -> impl Iterator<Item = (usize, usize)> {
|
||||||
(0..BOARD_SIZE)
|
(0..Self::BOARD_SIZE)
|
||||||
.map(|i| (i, BOARD_SIZE - 1))
|
.map(|i| (i, Self::BOARD_SIZE - 1))
|
||||||
.chain((0..BOARD_SIZE).map(|i| (i, 0)))
|
.chain((0..Self::BOARD_SIZE).map(|i| (i, 0)))
|
||||||
.chain((0..BOARD_SIZE).map(|j| (BOARD_SIZE - 1, j)))
|
.chain((0..Self::BOARD_SIZE).map(|j| (Self::BOARD_SIZE - 1, j)))
|
||||||
.chain((0..BOARD_SIZE).map(|j| (0, j)))
|
.chain((0..Self::BOARD_SIZE).map(|j| (0, j)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn corners() -> impl Iterator<Item = (usize, usize)> {
|
||||||
|
[0, Self::BOARD_SIZE - 1]
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|i| [0, Self::BOARD_SIZE - 1].into_iter().map(move |j| (i, j)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to a backing [`BitBoard`]
|
/// Get a reference to a backing [`BitBoard`]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user