This commit is contained in:
Simon Gardling 2025-02-12 21:24:35 -05:00
parent 2c241948f7
commit 351953450a
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D
6 changed files with 36 additions and 78 deletions

46
Cargo.lock generated
View File

@ -44,31 +44,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "either"
version = "1.13.0"
@ -188,7 +163,6 @@ dependencies = [
"lazy_static",
"num",
"rand",
"rayon",
"static_assertions",
]
@ -256,26 +230,6 @@ dependencies = [
"zerocopy 0.8.17",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "static_assertions"
version = "1.1.0"

View File

@ -14,5 +14,4 @@ either = "1.13"
lazy_static = "1.5.0"
num = "0.4"
rand = "0.9"
rayon = "1.10"
static_assertions = "1.1"

View File

@ -14,7 +14,7 @@ pub struct ManualAgent {
}
impl Agent for ManualAgent {
fn next_move(&mut self, _: &Board) -> Option<(usize, usize)> {
fn next_move(&mut self, board: &Board) -> Option<(usize, usize)> {
let stdin = io::stdin();
let mut input = String::new();
println!("Your turn! ('Skip' to skip)");
@ -34,8 +34,12 @@ impl Agent for ManualAgent {
.and_then(|x| -> Option<[usize; 2]> { x.try_into().ok() })
.map(|x| (x[0], x[1]));
if got.is_some() {
return got;
if let Some(got) = got {
if board.possible_moves(self.color).all(|x| x != got) {
println!("Invalid move! Try again.");
continue;
}
return Some(got);
}
}
}

View File

@ -233,12 +233,16 @@ impl Board {
fill
}
pub fn count(&self, piece: Piece) -> usize {
match piece {
Piece::Black => self.black_board.count(),
Piece::White => self.white_board.count(),
}
}
/// Returns (White score, Black score)
pub fn get_score(&self) -> (usize, usize) {
(
self.white_board.count() as usize,
self.black_board.count() as usize,
)
(self.count(Piece::White), self.count(Piece::Black))
}
pub fn game_winner(&self, turn: Piece) -> Option<Piece> {

View File

@ -1,5 +1,4 @@
use crate::{agent::Agent, board::Board, piece::Piece};
use rayon::prelude::*;
#[derive(Clone)]
struct Move {
@ -33,7 +32,7 @@ struct Move {
impl Move {
fn compute_self_value(&self, agent_color: Piece, depth: usize) -> i64 {
let mut self_value = self.captured as i64;
let mut self_value = self.board.count(agent_color) as i64;
if self.winner == Some(!agent_color) {
// if this board results in the opponent winning, MAJORLY negatively weigh this move
@ -43,8 +42,6 @@ impl Move {
} else if self.winner == Some(agent_color) {
// results in a win for the agent
self_value = i64::MAX;
} else if self.color != agent_color {
self_value = -self_value;
}
self_value / depth as i64
@ -87,24 +84,24 @@ impl FutureMoves {
color: Piece,
remaining_depth: usize,
) {
if remaining_depth == 0 {
return;
self.current_depth += remaining_depth;
let mut next_nodes: Vec<usize> = nodes.collect();
let mut next_color = !color;
for _ in 0..remaining_depth {
next_nodes = next_nodes
.into_iter()
.flat_map(|node_idx| {
self.generate_children(
Some(node_idx),
&self.arena[node_idx].board.clone(),
next_color,
)
})
.collect();
next_color = !next_color;
}
let next_color = !color;
let next_nodes: Vec<usize> = nodes
.flat_map(|node_idx| {
self.generate_children(
Some(node_idx),
&self.arena[node_idx].board.clone(),
next_color,
)
})
.collect();
self.current_depth += 1;
self.extend_layers(next_nodes.into_iter(), next_color, remaining_depth - 1);
}
fn generate_children(
@ -225,9 +222,9 @@ impl FutureMoves {
let mut index_map = vec![None; self.arena.len()];
// PERF: reverse iterator to avoid unneeded `memcpy`s when deconstructing the Arena
for (old_idx, keep) in retain.iter().enumerate().rev() {
for (old_idx, keep) in retain.into_iter().enumerate().rev() {
let mut node = self.arena.remove(old_idx);
if *keep {
if keep {
index_map[old_idx] = Some(new_arena.len());
node.parent = node.parent.and_then(|p| index_map[p]);

View File

@ -60,7 +60,7 @@ impl Game {
// Lets the player try again if the move is invalid
// Now we dont need to restart the game if we mess up
Err(err) => {
println!("Invalid move by Player {}: {}. Try again.", player_i, err);
panic!("Invalid move by Player {}: {}. Try again.", player_i, err);
}
}
} else {