cleanup minmax impl
This commit is contained in:
parent
9342760d82
commit
111ce718da
@ -30,7 +30,7 @@ pub fn run() {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let configs = [2, 4, 6, 8]
|
let configs = [2, 4, 6]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |d| FutureMoveConfig {
|
.map(move |d| FutureMoveConfig {
|
||||||
max_depth: d,
|
max_depth: d,
|
||||||
|
|||||||
@ -213,18 +213,7 @@ impl FutureMoves {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_move(&self, coord: MoveCoord, board: Board, color: Piece) -> Move {
|
fn create_move(&self, coord: MoveCoord, board: Board, color: Piece) -> Move {
|
||||||
Move::new(
|
Move::new(coord, board, color, self.agent_color, MoveValueConfig {})
|
||||||
coord,
|
|
||||||
board,
|
|
||||||
color,
|
|
||||||
self.agent_color,
|
|
||||||
MoveValueConfig {
|
|
||||||
self_value_raw: matches!(
|
|
||||||
self.config.children_eval_method,
|
|
||||||
ChildrenEvalMethod::MinMaxProb
|
|
||||||
),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_children_raw(&self, parent_idx: usize) -> Vec<Move> {
|
fn generate_children_raw(&self, parent_idx: usize) -> Vec<Move> {
|
||||||
@ -307,38 +296,27 @@ impl FutureMoves {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|&child| self.arena[child].value)
|
.map(|&child| self.arena[child].value)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
let child_value = if self.arena[idx].color == self.agent_color {
|
||||||
|
// get best (for the adversary) enemy play
|
||||||
|
// this assumes the adversary is playing optimally
|
||||||
|
|
||||||
|
children_values.iter().min()
|
||||||
|
} else {
|
||||||
|
children_values.iter().max()
|
||||||
|
}
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(Default::default());
|
||||||
|
self.arena[idx].value = self.arena[idx].self_value;
|
||||||
|
|
||||||
match self.config.children_eval_method {
|
match self.config.children_eval_method {
|
||||||
ChildrenEvalMethod::MinMax => {
|
ChildrenEvalMethod::MinMax => {
|
||||||
let child_value = if self.arena[idx].color == self.agent_color {
|
self.arena[idx].value.value += child_value.value;
|
||||||
// get best (for the adversary) enemy play
|
|
||||||
// this assumes the adversary is playing optimally
|
|
||||||
|
|
||||||
children_values.into_iter().map(|x| x.value).min()
|
|
||||||
} else {
|
|
||||||
children_values.into_iter().map(|x| x.value).max()
|
|
||||||
}
|
|
||||||
.unwrap_or(0);
|
|
||||||
|
|
||||||
self.arena[idx].value.value =
|
|
||||||
self.arena[idx].self_value.value + child_value;
|
|
||||||
}
|
}
|
||||||
ChildrenEvalMethod::MinMaxProb => {
|
ChildrenEvalMethod::MinMaxProb => {
|
||||||
let child_value = if self.arena[idx].color == self.agent_color {
|
|
||||||
// get best (for the adversary) enemy play
|
|
||||||
// this assumes the adversary is playing optimally
|
|
||||||
|
|
||||||
children_values.iter().min()
|
|
||||||
} else {
|
|
||||||
children_values.iter().max()
|
|
||||||
}
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(Default::default());
|
|
||||||
|
|
||||||
self.arena[idx].value = self.arena[idx].self_value;
|
|
||||||
self.arena[idx]
|
self.arena[idx]
|
||||||
.value
|
.value
|
||||||
.populate_self_from_children(&children_values);
|
.populate_self_from_children(&children_values);
|
||||||
|
|
||||||
self.arena[idx].value.value += child_value.value;
|
self.arena[idx].value.value += child_value.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,9 +38,7 @@ pub struct Move {
|
|||||||
pub is_trimmed: bool,
|
pub is_trimmed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MoveValueConfig {
|
pub struct MoveValueConfig {}
|
||||||
pub self_value_raw: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Move {
|
impl Move {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@ -48,7 +46,7 @@ impl Move {
|
|||||||
board: Board,
|
board: Board,
|
||||||
color: Piece,
|
color: Piece,
|
||||||
agent_color: Piece,
|
agent_color: Piece,
|
||||||
mvc: MoveValueConfig,
|
_: MoveValueConfig,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut m = Move {
|
let mut m = Move {
|
||||||
coord,
|
coord,
|
||||||
@ -76,30 +74,11 @@ impl Move {
|
|||||||
Winner::None => {}
|
Winner::None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if mvc.self_value_raw {
|
m.self_value.value =
|
||||||
m.self_value.value =
|
const { BoardValueMap::weighted() }.board_value(&board, agent_color) as i32;
|
||||||
const { BoardValueMap::weighted() }.board_value(&board, agent_color) as i32;
|
|
||||||
} else {
|
|
||||||
m.self_value.value = m.compute_self_value(agent_color, &board, mvc) as i32;
|
|
||||||
}
|
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_self_value(&self, agent_color: Piece, board: &Board, _mvc: MoveValueConfig) -> i16 {
|
|
||||||
if self.winner == Winner::Player(!agent_color) {
|
|
||||||
// if this board results in the opponent winning, MAJORLY negatively weigh this move
|
|
||||||
// NOTE! this branch isn't completely deleted because if so, the bot wouldn't make a move.
|
|
||||||
// We shouldn't prune branches because we still need to always react to the opponent's moves
|
|
||||||
return i16::MIN + 1;
|
|
||||||
} else if self.winner == Winner::Player(agent_color) {
|
|
||||||
// results in a win for the agent
|
|
||||||
return i16::MAX - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// I guess ignore Ties here, don't give them an explicit value,
|
|
||||||
const { BoardValueMap::weighted() }.board_value(board, agent_color)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sort children of the [`Move`] by their self_value in `arena`
|
/// Sort children of the [`Move`] by their self_value in `arena`
|
||||||
pub fn sort_children(&mut self, arena: &[Move]) {
|
pub fn sort_children(&mut self, arena: &[Move]) {
|
||||||
self.children.sort_by(|&a, &b| {
|
self.children.sort_by(|&a, &b| {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user