From d29095bc9dad30a85693db12f7756d68592839a7 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Thu, 20 Feb 2025 19:14:31 -0500 Subject: [PATCH] place weighting --- Cargo.lock | 33 ++++++++++++--- Cargo.toml | 1 + src/complexagent.rs | 2 +- src/logic/board_value.rs | 10 +++-- src/logic/move.rs | 2 +- src/main.rs | 4 +- src/repr/bitboard.rs | 14 +++---- src/repr/board.rs | 86 +++++++++++++++++++++++++--------------- 8 files changed, 101 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0801c46..80badea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -129,6 +129,17 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "console" version = "0.15.10" @@ -431,6 +442,7 @@ version = "0.1.0" dependencies = [ "arrayvec", "bitvec", + "comptime", "const_fn", "criterion", "either", @@ -626,7 +638,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.98", ] [[package]] @@ -647,6 +659,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "syn" version = "2.0.98" @@ -727,7 +750,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.98", "wasm-bindgen-shared", ] @@ -749,7 +772,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -910,7 +933,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.98", ] [[package]] @@ -921,5 +944,5 @@ checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.98", ] diff --git a/Cargo.toml b/Cargo.toml index d9b5dd9..62f7bb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ bitvec = [ "dep:bitvec" ] [dependencies] arrayvec = "0.7" bitvec = { version = "1", optional = true } +comptime = "1.0.0" const_fn = "0.4.11" either = "1.13" indicatif = "0.17" diff --git a/src/complexagent.rs b/src/complexagent.rs index ac54f8b..0e0f48e 100644 --- a/src/complexagent.rs +++ b/src/complexagent.rs @@ -15,7 +15,7 @@ impl ComplexAgent { const MAX_DEPTH: usize = 12; Self { color, - future_moves: FutureMoves::new(color, MAX_DEPTH, 4), + future_moves: FutureMoves::new(color, MAX_DEPTH, 6), } } } diff --git a/src/logic/board_value.rs b/src/logic/board_value.rs index b837990..79535c0 100644 --- a/src/logic/board_value.rs +++ b/src/logic/board_value.rs @@ -1,9 +1,9 @@ use crate::repr::{Board, Piece, PosMap}; -pub struct BoardValueMap(PosMap); +pub struct BoardValueMap(PosMap); 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() .filter_map(|(i, j)| board.get(i, j).map(|p| (i, j, p))) .map(|(i, j, pos_p)| { @@ -25,7 +25,11 @@ impl BoardValueMap { } 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) diff --git a/src/logic/move.rs b/src/logic/move.rs index 0794ad3..ce0a4f6 100644 --- a/src/logic/move.rs +++ b/src/logic/move.rs @@ -55,6 +55,6 @@ impl Move { return 0; } - BVM.board_value(&self.board, agent_color) as i64 + BVM.board_value(&self.board, agent_color) } } diff --git a/src/main.rs b/src/main.rs index 82924e5..e6672a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,8 +10,8 @@ pub mod repr; fn main() { let player1 = complexagent::ComplexAgent::new(Piece::Black); // let player2 = complexagent::ComplexAgent::new(Piece::White); - let player2 = agent::ManualAgent::new(Piece::White); - // let player2 = agent::RandomAgent::new(Piece::White); + // let player2 = agent::ManualAgent::new(Piece::White); + let player2 = agent::RandomAgent::new(Piece::White); let mut game = Game::new(Box::new(player1), Box::new(player2)); game.game_loop(); } diff --git a/src/repr/bitboard.rs b/src/repr/bitboard.rs index c05306f..5e6e31f 100644 --- a/src/repr/bitboard.rs +++ b/src/repr/bitboard.rs @@ -1,4 +1,4 @@ -use crate::repr::board::{BOARD_AREA, BOARD_SIZE}; +use crate::repr::board::Board; use const_fn::const_fn; use static_assertions::const_assert; @@ -15,7 +15,7 @@ use bitvec::prelude::*; type BBBaseType = u64; #[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"))] pub type BitBoardInner = u64; @@ -24,7 +24,7 @@ pub type BitBoardInner = u64; pub struct BitBoard(BitBoardInner); // BitBoard should be big enough to fit all points on the board -const_assert!(std::mem::size_of::() * 8 >= BOARD_AREA); +const_assert!(std::mem::size_of::() * 8 >= Board::BOARD_AREA); impl Default for BitBoard { fn default() -> Self { @@ -35,7 +35,7 @@ impl Default for BitBoard { impl BitBoard { #[cfg(feature = "bitvec")] pub const fn new() -> Self { - Self(bitarr!(BBBaseType, Lsb0; 0; BOARD_AREA)) + Self(bitarr!(BBBaseType, Lsb0; 0; Board::BOARD_AREA)) } #[cfg(not(feature = "bitvec"))] @@ -57,7 +57,7 @@ impl BitBoard { } const fn get_index(row: usize, col: usize) -> usize { - row * BOARD_SIZE + col + row * Board::BOARD_SIZE + col } #[cfg(feature = "bitvec")] @@ -84,8 +84,8 @@ mod test { #[test] fn set_and_get() { let mut b = BitBoard::new(); - for i in 0..BOARD_SIZE { - for j in 0..BOARD_SIZE { + for i in 0..Board::BOARD_SIZE { + for j in 0..Board::BOARD_SIZE { assert!( !b.get(i, j), "A just-initalized BitBoard should be completely empty" diff --git a/src/repr/board.rs b/src/repr/board.rs index a368ae1..76d2298 100644 --- a/src/repr/board.rs +++ b/src/repr/board.rs @@ -8,34 +8,33 @@ use const_fn::const_fn; use lazy_static::lazy_static; 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 -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....) type ChainCollection = ArrayVec; +const BOARD_AREA: usize = Board::BOARD_AREA; + /// Map of all points on the board against some type T /// Used to index like so: example[i][j] /// with each coordinate pub struct PosMap(ArrayVec); +impl Default for PosMap { + fn default() -> Self { + Self::new() + } +} + impl PosMap { const fn index(row: usize, col: usize) -> usize { - row * BOARD_SIZE + col + row * Board::BOARD_SIZE + col } pub fn new() -> Self { Self(ArrayVec::from_iter( - (0..BOARD_AREA).map(|_| Default::default()), + (0..Board::BOARD_AREA).map(|_| Default::default()), )) } @@ -43,7 +42,7 @@ impl PosMap { let index = Self::index(row, col); debug_assert!( - BOARD_AREA + 1 >= index, + Board::BOARD_AREA + 1 >= index, "index out of range, was: {}", index ); @@ -54,7 +53,7 @@ impl PosMap { pub fn set(&mut self, row: usize, col: usize, value: T) { let index = Self::index(row, col); debug_assert!( - BOARD_AREA + 1 >= index, + Board::BOARD_AREA + 1 >= index, "index out of range, was: {}", index ); @@ -69,8 +68,8 @@ fn gen_adj_lookup() -> PosMap { Board::all_positions() .map(|(i, j)| { let (i_chain, j_chain) = ( - split_from(0..=BOARD_SIZE - 1, i), - split_from(0..=BOARD_SIZE - 1, j), + split_from(0..=Board::BOARD_SIZE - 1, i), + split_from(0..=Board::BOARD_SIZE - 1, j), ); let chains: ChainCollection = ArrayVec::from_iter( @@ -95,7 +94,7 @@ fn gen_adj_lookup() -> PosMap { .iter() .flatten() .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" ); @@ -138,25 +137,25 @@ pub struct Board { impl fmt::Display for Board { #[allow(clippy::repeat_once)] // clippy gets mad about when PADDING == 1 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 - 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); // Print numbers at top so the board can be read more easier write!(f, "{} ", space_padding)?; - for j in (0..BOARD_SIZE).rev() { + for j in (0..Self::BOARD_SIZE).rev() { write!(f, "{:0PADDING$} ", j)?; } writeln!(f)?; - for i in (0..BOARD_SIZE).rev() { + for i in (0..Self::BOARD_SIZE).rev() { writeln!(f, "{}{}", space_padding, horiz_sep_line)?; write!(f, "{:0PADDING$}|", i)?; - for j in (0..BOARD_SIZE).rev() { + for j in (0..Self::BOARD_SIZE).rev() { write!( f, "{}|", @@ -194,6 +193,11 @@ impl Default for 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 pub const fn new() -> Self { Self { @@ -205,16 +209,28 @@ impl Board { /// Starting position #[const_fn(cfg(not(feature = "bitvec")))] pub const fn starting_pos(mut self) -> Self { - self.place_unchecked((BOARD_SIZE / 2) - 1, (BOARD_SIZE / 2) - 1, Piece::White); - self.place_unchecked(BOARD_SIZE / 2, (BOARD_SIZE / 2) - 1, Piece::Black); - self.place_unchecked((BOARD_SIZE / 2) - 1, BOARD_SIZE / 2, Piece::Black); - self.place_unchecked(BOARD_SIZE / 2, BOARD_SIZE / 2, Piece::White); + self.place_unchecked( + (Self::BOARD_SIZE / 2) - 1, + (Self::BOARD_SIZE / 2) - 1, + 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 } /// Provides an iterator of all possible positions on the board pub fn all_positions() -> impl Iterator { - (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 @@ -223,11 +239,17 @@ impl Board { } pub fn sides() -> impl Iterator { - (0..BOARD_SIZE) - .map(|i| (i, BOARD_SIZE - 1)) - .chain((0..BOARD_SIZE).map(|i| (i, 0))) - .chain((0..BOARD_SIZE).map(|j| (BOARD_SIZE - 1, j))) - .chain((0..BOARD_SIZE).map(|j| (0, j))) + (0..Self::BOARD_SIZE) + .map(|i| (i, Self::BOARD_SIZE - 1)) + .chain((0..Self::BOARD_SIZE).map(|i| (i, 0))) + .chain((0..Self::BOARD_SIZE).map(|j| (Self::BOARD_SIZE - 1, j))) + .chain((0..Self::BOARD_SIZE).map(|j| (0, j))) + } + + pub fn corners() -> impl Iterator { + [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`]