wip incremental distance update
This commit is contained in:
parent
2bf743a272
commit
3bd28451e9
3 changed files with 55 additions and 14 deletions
|
|
@ -201,12 +201,20 @@ impl Default for GameState {
|
|||
|
||||
impl Display for GameState {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let dm = GoalDistanceMap::new(&self.walls, self.current_player);
|
||||
let d1 = GoalDistanceMap::new(&self.walls, PlayerIdentifier::P1);
|
||||
let d2 = GoalDistanceMap::new(&self.walls, PlayerIdentifier::P2);
|
||||
|
||||
writeln!(
|
||||
f,
|
||||
"P1: {}, P2: {}\n",
|
||||
self.p1.walls_left, self.p2.walls_left
|
||||
"P1: {} walls, {} away from win",
|
||||
self.p1.walls_left,
|
||||
d1.at(self.p1.x(), self.p1.y())
|
||||
)?;
|
||||
writeln!(
|
||||
f,
|
||||
"P2: {} walls, {} away from win",
|
||||
self.p2.walls_left,
|
||||
d2.at(self.p2.x(), self.p2.y())
|
||||
)?;
|
||||
writeln!(f, "┏━━┬━━┬━━┬━━┬━━┬━━┬━━┬━━┬━━┓")?;
|
||||
for y in 0..9 {
|
||||
|
|
@ -237,11 +245,12 @@ impl Display for GameState {
|
|||
write!(f, "{wall}")?;
|
||||
}
|
||||
let player = if self.p1.x() == x && self.p1.y() == y {
|
||||
"\x1b[1mP1\x1b[0m".to_string()
|
||||
"\x1b[1mP1\x1b[0m".to_owned()
|
||||
} else if self.p2.x() == x && self.p2.y() == y {
|
||||
"\x1b[1mP2\x1b[0m".to_string()
|
||||
"\x1b[1mP2\x1b[0m".to_owned()
|
||||
} else {
|
||||
format!("{:^2}", dm.at(x, y))
|
||||
// format!("{:^2}", dm.at(x, y))
|
||||
" ".to_owned()
|
||||
};
|
||||
write!(f, "{player}")?;
|
||||
}
|
||||
|
|
|
|||
17
src/main.rs
17
src/main.rs
|
|
@ -81,6 +81,11 @@ impl Game<NUM_NEXT_STATES> for Quoridor {
|
|||
} else {
|
||||
self.state.walls.can_walk_between(x, y, x, y + 1)
|
||||
};
|
||||
if self.state.current_player_state().walls_left == 0 {
|
||||
if res[..128].iter().any(|x| *x) {
|
||||
panic!("{res:?}")
|
||||
}
|
||||
}
|
||||
// TODO: detect jumps for the 4 directions and also blocked jumps for the 2 sides of the other pawn
|
||||
res
|
||||
}
|
||||
|
|
@ -90,7 +95,7 @@ impl Game<NUM_NEXT_STATES> for Quoridor {
|
|||
}
|
||||
|
||||
fn play(&mut self, action: usize) {
|
||||
if action <= 128 {
|
||||
if action < 128 {
|
||||
self.state.current_player_state_mut().walls_left -= 1;
|
||||
}
|
||||
let mut set_block = |i: usize, vertical| {
|
||||
|
|
@ -171,23 +176,19 @@ fn main() -> Result<(), MctsError> {
|
|||
let mut mcts: Mcts<Quoridor, _> = Mcts::<Quoridor, _>::new();
|
||||
let evaluator = ProgressEvaluator;
|
||||
|
||||
for _ in 0..100 {
|
||||
// Perform 100 MCTS iterations
|
||||
for _ in 0..10_000 {
|
||||
while g.get_result().is_none() {
|
||||
for _ in 0..5000 {
|
||||
mcts.iterate(&evaluator)?;
|
||||
}
|
||||
|
||||
// Get the best action based on visit counts
|
||||
let (score, policy) = mcts.get_result();
|
||||
println!("Best action score: {}, Policy: {:?}", score, policy);
|
||||
|
||||
// Play the best action and update the MCTS tree
|
||||
let best_action_index = policy
|
||||
.iter()
|
||||
.enumerate()
|
||||
.max_by(|&(_, &a), &(_, &b)| a.partial_cmp(&b).unwrap())
|
||||
.map(|(index, _)| index)
|
||||
.unwrap_or(0); // Default to first action if policy is empty
|
||||
.unwrap_or(0);
|
||||
|
||||
// let mut x = policy.iter().enumerate().collect::<Vec<_>>();
|
||||
// x.sort_by(|&(_, &a), &(_, &b)| a.total_cmp(&b));
|
||||
|
|
|
|||
|
|
@ -38,6 +38,37 @@ impl GoalDistanceMap {
|
|||
Self { distances: res }
|
||||
}
|
||||
|
||||
pub fn add_wall(&mut self, w: &mut WallState, x: u8, y: u8, vertical: bool) {
|
||||
// TODO: we just realized that actually you have to search from the 4 invalidated
|
||||
// nodes and then propagate back when you've found a distance that's minus 1 from a
|
||||
// trusted node
|
||||
w.place(x, y, vertical);
|
||||
let invalidate = [(x, y), (x + 1, y), (x, y + 1), (x + 1, y + 1)];
|
||||
for (x, y) in invalidate {
|
||||
self.distances[y as usize][x as usize] = u8::MAX;
|
||||
}
|
||||
let mut todo = VecDeque::from(invalidate.map(|(x, y)| ((x, y), self.at(x, y))));
|
||||
while let Some(((x, y), distance)) = todo.pop_front() {
|
||||
if self.distances[y as usize][x as usize] == distance - 1 {
|
||||
continue;
|
||||
}
|
||||
self.distances[y as usize][x as usize] = distance;
|
||||
|
||||
if x > 0 && w.can_walk_between(x, y, x - 1, y) {
|
||||
todo.push_back(((x - 1, y), distance - 1));
|
||||
}
|
||||
if x < 8 && w.can_walk_between(x, y, x + 1, y) {
|
||||
todo.push_back(((x + 1, y), distance - 1));
|
||||
}
|
||||
if y > 0 && w.can_walk_between(x, y, x, y - 1) {
|
||||
todo.push_back(((x, y - 1), distance - 1));
|
||||
}
|
||||
if y < 8 && w.can_walk_between(x, y, x, y + 1) {
|
||||
todo.push_back(((x, y + 1), distance - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn at(&self, x: u8, y: u8) -> u8 {
|
||||
self.distances[y as usize][x as usize]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue