make complexagent so much better
This commit is contained in:
parent
3681fd7e41
commit
669af2a56e
32
src/board.rs
32
src/board.rs
@ -6,7 +6,7 @@ use std::{cmp::Ordering, fmt};
|
||||
|
||||
pub const BOARD_SIZE: usize = 8;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Board {
|
||||
board: [[Option<Piece>; BOARD_SIZE]; BOARD_SIZE],
|
||||
}
|
||||
@ -78,7 +78,7 @@ impl Board {
|
||||
Box::new(
|
||||
(0..BOARD_SIZE)
|
||||
.flat_map(|i| (0..BOARD_SIZE).map(move |j| (i, j)))
|
||||
.filter(move |(i, j)| self.what_if(*i, *j, color).is_some()),
|
||||
.filter(move |(i, j)| self.would_prop(*i, *j, color)),
|
||||
)
|
||||
}
|
||||
|
||||
@ -111,6 +111,10 @@ impl Board {
|
||||
Some((self_copy, how_many_prop))
|
||||
}
|
||||
|
||||
pub fn would_prop(&self, i: usize, j: usize, piece: Piece) -> bool {
|
||||
!self.propegate_from_dry(i, j, piece).is_empty()
|
||||
}
|
||||
|
||||
pub fn place(&mut self, i: usize, j: usize, piece: Piece) -> Result<(), String> {
|
||||
if let Some(what_if_result) = self.what_if(i, j, piece) {
|
||||
if what_if_result.1 > 0 {
|
||||
@ -121,15 +125,24 @@ impl Board {
|
||||
Err("move would not propegate".to_string())
|
||||
}
|
||||
|
||||
/// Propegate piece captures originating from (i, j)
|
||||
/// DO NOT USE THIS ALONE, this should be called as a part of
|
||||
/// [`Board::place`] or [`Board::place_and_prop_unchecked`]
|
||||
fn propegate_from(&mut self, i: usize, j: usize) -> usize {
|
||||
// returns if that place is empty
|
||||
let Some(starting_color) = *self.get(i, j) else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
let pos_s = self.propegate_from_dry(i, j, starting_color);
|
||||
let pos_len = pos_s.len();
|
||||
for (i, j) in pos_s {
|
||||
self.place_unchecked(i, j, starting_color);
|
||||
}
|
||||
|
||||
pos_len
|
||||
}
|
||||
|
||||
/// Propegate piece captures originating from (i, j)
|
||||
/// DO NOT USE THIS ALONE, this should be called as a part of
|
||||
/// [`Board::place`] or [`Board::place_and_prop_unchecked`]
|
||||
fn propegate_from_dry(&self, i: usize, j: usize, starting_color: Piece) -> Vec<(usize, usize)> {
|
||||
// Create all chains from the piece being propegated from in `i` and `j` coordinates
|
||||
let (i_chain, j_chain) = (
|
||||
split_from(0, BOARD_SIZE - 1, i),
|
||||
@ -152,7 +165,7 @@ impl Board {
|
||||
// handle diagonals
|
||||
chains.extend(diag(i, j, 0, 0, BOARD_SIZE - 1, BOARD_SIZE - 1));
|
||||
|
||||
let mut captured: usize = 0;
|
||||
let mut fill: Vec<(usize, usize)> = Vec::new();
|
||||
|
||||
for chain in chains {
|
||||
for (chain_length, &(new_i, new_j)) in chain.iter().enumerate() {
|
||||
@ -166,11 +179,10 @@ impl Board {
|
||||
let Some(history) = chain.get(..chain_length) else {
|
||||
break;
|
||||
};
|
||||
captured += history.len();
|
||||
|
||||
// fill all opposite colors with this color
|
||||
for &(i_o, j_o) in history {
|
||||
self.place_unchecked(i_o, j_o, starting_color);
|
||||
fill.push((i_o, j_o));
|
||||
}
|
||||
// either the other pieces were replaced, or this was an invalid chain,
|
||||
// in both cases, the loop needs to be breaked
|
||||
@ -178,7 +190,7 @@ impl Board {
|
||||
}
|
||||
}
|
||||
}
|
||||
captured
|
||||
fill
|
||||
}
|
||||
|
||||
/// Returns (White score, Black score)
|
||||
|
||||
@ -2,8 +2,10 @@ use crate::{agent::Agent, board::Board, piece::Piece};
|
||||
|
||||
pub struct ComplexAgent {
|
||||
color: Piece,
|
||||
curr_move: Option<Move>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Move {
|
||||
i: usize,
|
||||
j: usize,
|
||||
@ -44,6 +46,10 @@ impl Move {
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
pub const fn coords(&self) -> (usize, usize) {
|
||||
(self.i, self.j)
|
||||
}
|
||||
}
|
||||
|
||||
fn problem_space(board: &Board, color: Piece) -> Box<dyn Iterator<Item = Move> + '_> {
|
||||
@ -65,14 +71,38 @@ fn problem_space(board: &Board, color: Piece) -> Box<dyn Iterator<Item = Move> +
|
||||
impl Agent for ComplexAgent {
|
||||
fn next_move(&mut self, board: &Board) -> Option<(usize, usize)> {
|
||||
const LOOPS: usize = 5;
|
||||
problem_space(board, self.color)
|
||||
.map(|mut x| {
|
||||
x.populate_next_moves(LOOPS);
|
||||
x
|
||||
})
|
||||
.map(|m| ((m.i, m.j), m.value(self.color)))
|
||||
.max_by_key(|a| a.1)
|
||||
.map(|a| a.0)
|
||||
|
||||
let curr_move: Move = self.curr_move.take().unwrap_or_else(|| Move {
|
||||
i: 0,
|
||||
j: 0,
|
||||
captured: 0,
|
||||
color: self.color,
|
||||
board: *board,
|
||||
next_move: vec![Move {
|
||||
i: 0,
|
||||
j: 0,
|
||||
captured: 0,
|
||||
color: !self.color,
|
||||
board: *board,
|
||||
next_move: problem_space(board, self.color).collect(),
|
||||
}],
|
||||
});
|
||||
|
||||
let mut other_player_move = curr_move
|
||||
.next_move
|
||||
.into_iter()
|
||||
.filter(|x| &x.board == board)
|
||||
.last()
|
||||
.unwrap();
|
||||
|
||||
other_player_move.populate_next_moves(LOOPS);
|
||||
|
||||
self.curr_move = other_player_move
|
||||
.next_move
|
||||
.into_iter()
|
||||
.max_by_key(|m| m.value(self.color));
|
||||
|
||||
self.curr_move.as_ref().map(Move::coords)
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
@ -86,6 +116,9 @@ impl Agent for ComplexAgent {
|
||||
|
||||
impl ComplexAgent {
|
||||
pub fn new(color: Piece) -> Self {
|
||||
Self { color }
|
||||
Self {
|
||||
color,
|
||||
curr_move: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user