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;
|
pub const BOARD_SIZE: usize = 8;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct Board {
|
pub struct Board {
|
||||||
board: [[Option<Piece>; BOARD_SIZE]; BOARD_SIZE],
|
board: [[Option<Piece>; BOARD_SIZE]; BOARD_SIZE],
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ impl Board {
|
|||||||
Box::new(
|
Box::new(
|
||||||
(0..BOARD_SIZE)
|
(0..BOARD_SIZE)
|
||||||
.flat_map(|i| (0..BOARD_SIZE).map(move |j| (i, j)))
|
.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))
|
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> {
|
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 let Some(what_if_result) = self.what_if(i, j, piece) {
|
||||||
if what_if_result.1 > 0 {
|
if what_if_result.1 > 0 {
|
||||||
@ -121,15 +125,24 @@ impl Board {
|
|||||||
Err("move would not propegate".to_string())
|
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 {
|
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 {
|
let Some(starting_color) = *self.get(i, j) else {
|
||||||
return 0;
|
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
|
// Create all chains from the piece being propegated from in `i` and `j` coordinates
|
||||||
let (i_chain, j_chain) = (
|
let (i_chain, j_chain) = (
|
||||||
split_from(0, BOARD_SIZE - 1, i),
|
split_from(0, BOARD_SIZE - 1, i),
|
||||||
@ -152,7 +165,7 @@ impl Board {
|
|||||||
// handle diagonals
|
// handle diagonals
|
||||||
chains.extend(diag(i, j, 0, 0, BOARD_SIZE - 1, BOARD_SIZE - 1));
|
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 in chains {
|
||||||
for (chain_length, &(new_i, new_j)) in chain.iter().enumerate() {
|
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 {
|
let Some(history) = chain.get(..chain_length) else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
captured += history.len();
|
|
||||||
|
|
||||||
// fill all opposite colors with this color
|
// fill all opposite colors with this color
|
||||||
for &(i_o, j_o) in history {
|
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,
|
// either the other pieces were replaced, or this was an invalid chain,
|
||||||
// in both cases, the loop needs to be breaked
|
// in both cases, the loop needs to be breaked
|
||||||
@ -178,7 +190,7 @@ impl Board {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
captured
|
fill
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns (White score, Black score)
|
/// Returns (White score, Black score)
|
||||||
|
|||||||
@ -2,8 +2,10 @@ use crate::{agent::Agent, board::Board, piece::Piece};
|
|||||||
|
|
||||||
pub struct ComplexAgent {
|
pub struct ComplexAgent {
|
||||||
color: Piece,
|
color: Piece,
|
||||||
|
curr_move: Option<Move>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct Move {
|
struct Move {
|
||||||
i: usize,
|
i: usize,
|
||||||
j: usize,
|
j: usize,
|
||||||
@ -44,6 +46,10 @@ impl Move {
|
|||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn coords(&self) -> (usize, usize) {
|
||||||
|
(self.i, self.j)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn problem_space(board: &Board, color: Piece) -> Box<dyn Iterator<Item = Move> + '_> {
|
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 {
|
impl Agent for ComplexAgent {
|
||||||
fn next_move(&mut self, board: &Board) -> Option<(usize, usize)> {
|
fn next_move(&mut self, board: &Board) -> Option<(usize, usize)> {
|
||||||
const LOOPS: usize = 5;
|
const LOOPS: usize = 5;
|
||||||
problem_space(board, self.color)
|
|
||||||
.map(|mut x| {
|
let curr_move: Move = self.curr_move.take().unwrap_or_else(|| Move {
|
||||||
x.populate_next_moves(LOOPS);
|
i: 0,
|
||||||
x
|
j: 0,
|
||||||
})
|
captured: 0,
|
||||||
.map(|m| ((m.i, m.j), m.value(self.color)))
|
color: self.color,
|
||||||
.max_by_key(|a| a.1)
|
board: *board,
|
||||||
.map(|a| a.0)
|
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 {
|
fn name(&self) -> &'static str {
|
||||||
@ -86,6 +116,9 @@ impl Agent for ComplexAgent {
|
|||||||
|
|
||||||
impl ComplexAgent {
|
impl ComplexAgent {
|
||||||
pub fn new(color: Piece) -> Self {
|
pub fn new(color: Piece) -> Self {
|
||||||
Self { color }
|
Self {
|
||||||
|
color,
|
||||||
|
curr_move: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user