1
Fork 0

stop searching after a million checks

This commit is contained in:
Andy Killorin 2023-12-22 20:12:26 -06:00
parent 5b858f3d3b
commit 4c75d7e451
Signed by: ank
GPG key ID: B6241CA3B552BCA4
3 changed files with 41 additions and 18 deletions

View file

@ -3,7 +3,7 @@ use time::OffsetDateTime;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use typetag::serde; use typetag::serde;
use crate::{blocks::{Vec3, Position, Direction}, turtle::TurtleCommander, tasks::Task, depot::Depots, mine::fill}; use crate::{blocks::{Vec3, Position, Direction}, turtle::TurtleCommander, tasks::{Task, TaskState}, depot::Depots, mine::fill};
pub async fn fell_tree(turtle: TurtleCommander, bottom: Vec3) -> Option<()> { pub async fn fell_tree(turtle: TurtleCommander, bottom: Vec3) -> Option<()> {
let mut log = bottom; let mut log = bottom;
@ -73,12 +73,12 @@ impl Task for TreeFarm {
}) })
} }
fn poll(&mut self) -> Option<Position> { fn poll(&mut self) -> TaskState {
let elapsed = OffsetDateTime::now_utc() - self.last_sweep; let elapsed = OffsetDateTime::now_utc() - self.last_sweep;
if elapsed.whole_minutes() <= 16 { if elapsed.whole_minutes() <= 16 {
return None; return TaskState::Waiting;
} }
self.last_sweep = OffsetDateTime::now_utc(); self.last_sweep = OffsetDateTime::now_utc();
Some(Position::new(self.position, Direction::North)) // request a turtle TaskState::Ready(Position::new(self.position, Direction::North)) // request a turtle
} }
} }

View file

@ -1,8 +1,11 @@
use crate::{ use crate::{
blocks::{World, Position, Direction, Vec3, WorldReadLock}, blocks::{World, Position, Direction, Vec3, WorldReadLock},
}; };
use log::trace;
use pathfinding::prelude::astar; use pathfinding::prelude::astar;
const LOOKUP_LIMIT: usize = 1_000_000;
pub async fn route_facing(from: Position, to: Vec3, world: &World) -> Option<Vec<Position>> { pub async fn route_facing(from: Position, to: Vec3, world: &World) -> Option<Vec<Position>> {
let facing = |p: &Position| { let facing = |p: &Position| {
let ahead = p.dir.unit() + p.pos; let ahead = p.dir.unit() + p.pos;
@ -23,18 +26,33 @@ pub async fn route(from: Position, to: Position, world: &World) -> Option<Vec<Po
route_to(from, to.pos, |p| p == &to, world).await route_to(from, to.pos, |p| p == &to, world).await
} }
async fn route_to<D>(from: Position, to: Vec3, done: D, world: &World) -> Option<Vec<Position>> async fn route_to<D>(from: Position, to: Vec3, mut done: D, world: &World) -> Option<Vec<Position>>
where D: FnMut(&Position) -> bool { where D: FnMut(&Position) -> bool {
// lock once, we'll be doing a lot of lookups // lock once, we'll be doing a lot of lookups
let world = world.clone().lock().await; let world = world.clone().lock().await;
let mut limit = LOOKUP_LIMIT;
let route = astar( let route = astar(
&from, &from,
move |p| next(p, &world), move |p| next(p, &world),
|p1| (p1.pos - &to).abs().sum() as u32, |p1| (p1.pos - &to).abs().sum() as u32,
done, |p| {
limit -= 1;
if limit == 0 {
return true
} else {
done(p)
}
},
)?; )?;
Some(route.0)
trace!("scanned {} states", LOOKUP_LIMIT-limit);
if limit != 0 {
Some(route.0)
} else {
None
}
} }
fn next(from: &Position, world: &WorldReadLock) -> Vec<(Position, u32)> { fn next(from: &Position, world: &WorldReadLock) -> Vec<(Position, u32)> {
@ -94,7 +112,7 @@ const GARBAGE: [&str; 11] = [
]; ];
/// time taken to go through uncharted territory (in turtle. calls) /// time taken to go through uncharted territory (in turtle. calls)
const UNKNOWN: Option<u32> = Some(1); const UNKNOWN: Option<u32> = Some(2);
// time to go somewhere // time to go somewhere
pub fn difficulty(name: &str) -> Option<u32> { pub fn difficulty(name: &str) -> Option<u32> {
@ -104,5 +122,5 @@ pub fn difficulty(name: &str) -> Option<u32> {
if GARBAGE.contains(&name) { if GARBAGE.contains(&name) {
return Some(2); return Some(2);
}; };
Some(140) // providing a value here means that tunneling through builds is possible (bad) None
} }

View file

@ -1,21 +1,22 @@
use std::sync::Arc;
use erased_serde::serialize_trait_object;
use log::info; use log::info;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::{Mutex, MutexGuard, RwLock, OwnedMutexGuard};
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use crate::LiveState;
use crate::names::Name; use crate::names::Name;
use crate::{turtle::{self, TurtleCommander}, blocks::Position}; use crate::{turtle::TurtleCommander, blocks::Position};
#[typetag::serde(tag = "type")] pub enum TaskState {
Ready(Position),
Waiting,
Complete,
}
#[typetag::serde(tag = "task")]
pub trait Task: Send + Sync { pub trait Task: Send + Sync {
/// Execute the task /// Execute the task
fn run(&mut self, turtle: TurtleCommander) -> JoinHandle<()>; fn run(&mut self, turtle: TurtleCommander) -> JoinHandle<()>;
/// Return Some if the task should be scheduled /// Return Some if the task should be scheduled
fn poll(&mut self) -> Option<Position>; fn poll(&mut self) -> TaskState;
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -67,7 +68,8 @@ impl Scheduler {
} }
for task in &mut self.tasks { for task in &mut self.tasks {
if let Some(position) = task.poll() { let poll = task.poll();
if let TaskState::Ready(position) = poll {
let closest_turtle = match free_turtles.iter_mut().zip(turtle_positions.iter()).min_by_key( |(_,p)| { let closest_turtle = match free_turtles.iter_mut().zip(turtle_positions.iter()).min_by_key( |(_,p)| {
p.manhattan(position) p.manhattan(position)
}) { }) {
@ -77,6 +79,9 @@ impl Scheduler {
closest_turtle.1 = Some(task.run(closest_turtle.0.clone())); closest_turtle.1 = Some(task.run(closest_turtle.0.clone()));
} }
if let TaskState::Complete = poll {
// TODO: removal
}
} }
} }