abstract away more coordinates

This commit is contained in:
2025-02-27 21:00:04 -05:00
parent 956386fb66
commit 6ae1726010
12 changed files with 251 additions and 204 deletions

View File

@@ -5,8 +5,8 @@ pub struct BoardValueMap(PosMap<i64>);
impl BoardValueMap {
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)| (*self.0.get(i, j), pos_p))
.filter_map(|coord| board.get(coord).map(|p| (coord, p)))
.map(|(coord, pos_p)| (*self.0.get(coord), pos_p))
.map(|(value, pos_p)| {
if pos_p != color {
// enemy has position

View File

@@ -1,6 +1,6 @@
use crate::{
logic::r#move::Move,
repr::{Board, Coord, Piece, Winner},
repr::{Board, CoordPair, Piece, Winner},
};
use indicatif::{ProgressIterator, ProgressStyle};
use std::{collections::HashMap, hash::BuildHasherDefault, ops::ControlFlow};
@@ -94,10 +94,10 @@ impl FutureMoves {
}
});
self.prune_bad_children();
// self.prune_bad_children();
self.current_depth += 1;
if cf.is_break() {
dbg!("extend_layers: early break ({})", self.arena_len());
println!("extend_layers: early break");
return;
}
}
@@ -130,14 +130,14 @@ impl FutureMoves {
// use [`Board::all_positions`] here instead of [`Board::possible_moves`]
// because we use [`Board::what_if`] later and we want to reduce calls to [`Board::propegate_from_dry`]
let mut new: Vec<Move> = Board::all_positions()
.flat_map(|(i, j)| {
.flat_map(|coord| {
parent
.board
.what_if(i, j, new_color)
.map(move |x| (i, j, x))
.what_if(coord, new_color)
.map(move |x| (coord, x))
})
.map(|(i, j, new_board)| {
Move::new(Some((i, j)), new_board, new_color, self.agent_color)
.map(|(coord, new_board)| {
Move::new(Some(coord), new_board, new_color, self.agent_color)
})
.collect();
@@ -200,32 +200,26 @@ impl FutureMoves {
// reversed so we build up the value of the closest (in time) moves from the future
for (depth, nodes) in by_depth_vec.into_iter().rev() {
for idx in nodes {
// TODO! impl dynamic sorting based on children's states, maybe it propegates
// upwards using the `parent` field
// let mut parent_copy = self.arena[idx].clone();
// parent_copy.sort_children(self.arena.as_mut_slice());
// self.arena[idx] = parent_copy;
let children_value = self.arena[idx]
.children
.iter()
.map(|&child| self.arena[child].value.expect("child has no value??"))
.sum::<i128>();
// average value of children
.sum::<i128>()
.checked_div(self.arena[idx].children.len() as i128)
.unwrap_or(0);
// we use `depth` and divided `self_value` by it, idk if this is worth it
// we should really setup some sort of ELO rating for each commit, playing them against
// each other or something, could be cool to benchmark these more subjective things, not
// just performance (cycles/time wise)
self.arena[idx].value = Some(
(self.arena[idx].self_value as i128 + children_value) / (depth + 1) as i128,
);
self.arena[idx].value = Some(self.arena[idx].self_value as i128 + children_value);
}
}
}
/// Return the best move which is a child of `self.current_root`
pub fn best_move(&self) -> Option<Option<(Coord, Coord)>> {
pub fn best_move(&self) -> Option<Option<CoordPair>> {
self.current_root
.and_then(|x| {
self.arena[x]
@@ -256,11 +250,11 @@ impl FutureMoves {
if let Some(curr_board_idx) = curr_board {
self.set_root_idx_raw(curr_board_idx);
return false;
false
} else {
dbg!("regenerating arena from board");
println!("regenerating arena from board");
self.set_root_from_board(*board);
return true;
true
}
}
@@ -269,6 +263,7 @@ impl FutureMoves {
self.arena.clear();
self.arena
.push(Move::new(None, board, !self.agent_color, self.agent_color));
// because we have to regenerate root from a [`Board`]
// we need to reset the current_depth (fixes `skip_move_recovery`)
self.current_depth = 0;
@@ -291,7 +286,7 @@ impl FutureMoves {
self.compute_values(0..self.arena.len());
// check arena's consistancy
assert_eq!(self.check_arena().join("\n"), "");
debug_assert_eq!(self.check_arena().join("\n"), "");
}
pub fn set_parent_child(&mut self, parent: usize, child: usize) {
@@ -485,7 +480,7 @@ mod tests {
// dummy (2)
futm.arena.push(Move::new(
Some((123, 123)),
Some((9, 9).into()),
Board::new(),
Piece::White,
Piece::Black,
@@ -509,7 +504,7 @@ mod tests {
assert_ne!(
futm.arena[2].coord,
Some((123, 123)),
Some((9, 9).into()),
"dummy value still exists"
);
}
@@ -682,8 +677,8 @@ mod tests {
}
}
if let Some((i, j)) = coords {
board.place(i, j, color).unwrap();
if let Some(coord) = coords {
board.place(coord.into(), color).unwrap();
}
}
}

View File

@@ -1,11 +1,11 @@
use super::board_value::BoardValueMap;
use crate::repr::{Board, Coord, Piece, Winner};
use crate::repr::{Board, CoordPair, Piece, Winner};
use lazy_static::lazy_static;
#[derive(Clone, Debug)]
pub struct Move {
/// Coordinates (i, j) of the move (if it exists)
pub coord: Option<(Coord, Coord)>,
pub coord: Option<CoordPair>,
/// [`Board`] state after move is made
pub board: Board,
@@ -40,12 +40,7 @@ lazy_static! {
}
impl Move {
pub fn new(
coord: Option<(Coord, Coord)>,
board: Board,
color: Piece,
agent_color: Piece,
) -> Self {
pub fn new(coord: Option<CoordPair>, board: Board, color: Piece, agent_color: Piece) -> Self {
let mut m = Move {
coord,
board,