1
Fork 0

dfs on ore find & ignore fluids in pathfinding

This commit is contained in:
Andy Killorin 2023-12-20 23:27:23 -06:00
parent 7d9cd93d1c
commit 7d2d85169f
Signed by: ank
GPG key ID: B6241CA3B552BCA4
4 changed files with 59 additions and 19 deletions

View file

@ -5,7 +5,7 @@ use rstar::{self, PointDistance, RTree, RTreeObject, AABB};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::{RwLock, RwLockReadGuard, OwnedRwLockReadGuard}; use tokio::sync::{RwLock, RwLockReadGuard, OwnedRwLockReadGuard};
use crate::{turtle::TurtleCommand, paths}; use crate::{turtle::TurtleCommand, paths::{self, TRANSPARENT}};
pub type WorldReadLock = OwnedRwLockReadGuard<RTree<Block>>; pub type WorldReadLock = OwnedRwLockReadGuard<RTree<Block>>;
@ -30,9 +30,9 @@ impl World {
self.state.write().await.insert(block); self.state.write().await.insert(block);
} }
/// Returns true if a known non-air block exists at the point /// Returns true if a known non-traversable block exists at the point
pub async fn occupied(&self, block: Vec3) -> bool { pub async fn occupied(&self, block: Vec3) -> bool {
self.state.read().await.locate_at_point(&block.into()).is_some_and(|b| b.name != "minecraft:air") self.state.read().await.locate_at_point(&block.into()).is_some_and(|b| !TRANSPARENT.contains(&b.name.as_str()))
} }
/// Returns true if a "garbage" block exists at the given point which you are free to destroy /// Returns true if a "garbage" block exists at the given point which you are free to destroy

View file

@ -212,11 +212,12 @@ async fn run_command(
async fn dig( async fn dig(
Path(id): Path<u32>, Path(id): Path<u32>,
State(state): State<SharedControl>, State(state): State<SharedControl>,
Json(req): Json<Vec3>, Json(req): Json<(Vec3, Position, Position)>,
) -> &'static str { ) -> &'static str {
let turtle = state.read().await.get_turtle(id).await.unwrap(); let turtle = state.read().await.get_turtle(id).await.unwrap();
let fuel = Position::new(Vec3::new(-19, 93, 73), blocks::Direction::East); let (req, fuel, inventory) = req;
let inventory = Position::new(Vec3::new(-19, 92, 73), blocks::Direction::East); //let fuel = Position::new(Vec3::new(-19, 93, 73), blocks::Direction::East);
//let inventory = Position::new(Vec3::new(-19, 92, 73), blocks::Direction::East);
tokio::spawn( tokio::spawn(
async move { async move {
mine::mine(turtle.clone(), req, fuel, inventory).await mine::mine(turtle.clone(), req, fuel, inventory).await

View file

@ -130,8 +130,9 @@ impl TurtleTask for TurtleMineJob {
use TurtleCommand::*; use TurtleCommand::*;
/// Things to leave in the field (not worth fuel) /// Things to leave in the field (not worth fuel)
const USELESS: [&str; 4] = [ const USELESS: [&str; 5] = [
"minecraft:dirt", "minecraft:dirt",
"minecraft:gravel",
"minecraft:cobblestone", "minecraft:cobblestone",
"minecraft:cobbled_deepslate", "minecraft:cobbled_deepslate",
"minecraft:diorite", "minecraft:diorite",
@ -150,17 +151,13 @@ pub async fn mine(turtle: TurtleCommander, pos: Vec3, fuel: Position, storage: P
loop { loop {
mine_chunk(turtle.clone(), pos, chunk).await?; mine_chunk(turtle.clone(), pos, chunk).await?;
turtle.world().lock().await valuables.append(&mut near_valuables(&turtle, pos, chunk).await);
.locate_within_distance(pos.into(), chunk.map(|n| n.pow(2)).sum())
.filter(|n| n.name != "minecraft:air")
.filter(|n| VALUABLE.iter().any(|v| n.name.contains(v)))
.map(|b|b.pos).collect_into(&mut valuables);
dump_filter(turtle.clone(), |i| USELESS.iter().any(|u| **u == i.name)).await;
while let Some(block) = valuables.pop() { while let Some(block) = valuables.pop() {
let near = turtle.goto_adjacent(block).await?; let near = turtle.goto_adjacent(block).await?;
turtle.execute(dbg!(near.dig(block))?).await; turtle.execute(dbg!(near.dig(block))?).await;
observe(turtle.clone(), block).await;
valuables.append(&mut near_valuables(&turtle, near.pos, Vec3::new(2,2,2)).await);
} }
if (turtle.fuel().await as f64) < (volume + (fuel.pos-turtle.pos().await.pos).abs().sum()) as f64 * 1.1 { if (turtle.fuel().await as f64) < (volume + (fuel.pos-turtle.pos().await.pos).abs().sum()) as f64 * 1.1 {
@ -169,7 +166,7 @@ pub async fn mine(turtle: TurtleCommander, pos: Vec3, fuel: Position, storage: P
refuel(turtle.clone()).await; refuel(turtle.clone()).await;
} }
if let turtle::TurtleCommandResponse::Item(_) = turtle.execute(ItemInfo(13)).await.ret { if dump_filter(turtle.clone(), |i| USELESS.iter().any(|u| **u == i.name)).await > 13 {
println!("storage rtb"); println!("storage rtb");
turtle.goto(storage).await?; turtle.goto(storage).await?;
dump(turtle.clone()).await; dump(turtle.clone()).await;
@ -179,6 +176,14 @@ pub async fn mine(turtle: TurtleCommander, pos: Vec3, fuel: Position, storage: P
} }
} }
async fn near_valuables(turtle: &TurtleCommander, pos: Vec3, chunk: Vec3) -> Vec<Vec3> {
turtle.world().lock().await
.locate_within_distance(pos.into(), chunk.map(|n| n.pow(2)).sum())
.filter(|n| n.name != "minecraft:air")
.filter(|n| VALUABLE.iter().any(|v| n.name.contains(v)))
.map(|b|b.pos).collect()
}
pub async fn mine_chunk(turtle: TurtleCommander, pos: Vec3, chunk: Vec3) -> Option<()> { pub async fn mine_chunk(turtle: TurtleCommander, pos: Vec3, chunk: Vec3) -> Option<()> {
let turtle = turtle.clone(); let turtle = turtle.clone();
let volume = chunk.x * chunk.y * chunk.z; let volume = chunk.x * chunk.y * chunk.z;
@ -224,15 +229,20 @@ async fn dump(turtle: TurtleCommander) {
} }
/// Dump all items that match the predicate /// Dump all items that match the predicate
async fn dump_filter<F>(turtle: TurtleCommander, mut filter: F) /// Returns the number of slots still full after the operation
async fn dump_filter<F>(turtle: TurtleCommander, mut filter: F) -> u32
where F: FnMut(InventorySlot) -> bool { where F: FnMut(InventorySlot) -> bool {
let mut counter = 0;
for i in 1..=16 { for i in 1..=16 {
if let TurtleCommandResponse::Item(item) = turtle.execute(Select(i)).await.ret { if let TurtleCommandResponse::Item(item) = turtle.execute(Select(i)).await.ret {
if filter(item) { if filter(item) {
turtle.execute(DropFront(64)).await; turtle.execute(DropFront(64)).await;
} else {
counter += 1;
} }
} }
} }
counter
} }
/// zig from 0 to x and back, stopping on each end /// zig from 0 to x and back, stopping on each end
@ -255,3 +265,26 @@ fn fill(scale: Vec3, n: i32) -> Vec3 {
step(n/scale.x/scale.y, scale.z) step(n/scale.x/scale.y, scale.z)
) )
} }
/// Looks at all the blocks around the given pos
/// destructive
async fn observe(turtle: TurtleCommander, pos: Vec3) -> Option<()> {
let adjacent = [
pos,
pos + Vec3::y(),
pos + Vec3::x(),
pos + Vec3::z(),
pos - Vec3::x(),
pos - Vec3::z(),
pos - Vec3::y(),
];
for pos in adjacent {
if turtle.world().get(pos).await.is_none() {
turtle.goto_adjacent(pos).await?;
}
}
Some(())
}

View file

@ -35,8 +35,7 @@ where D: FnMut(&Position) -> bool {
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, done,
) )?;
.unwrap();
Some(route.0) Some(route.0)
} }
@ -74,6 +73,13 @@ fn next(from: &Position, world: &WorldReadLock) -> Vec<(Position, u32)> {
vec vec
} }
/// Blocks that you can go through without a pickaxe
pub const TRANSPARENT: [&str; 3] = [
"minecraft:air",
"minecraft:water",
"minecraft:lava",
];
/// Blocks that are fine to tunnel through /// Blocks that are fine to tunnel through
const GARBAGE: [&str; 6] = [ const GARBAGE: [&str; 6] = [
"minecraft:stone", "minecraft:stone",
@ -89,7 +95,7 @@ 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> {
if name == "minecraft:air" { if TRANSPARENT.contains(&name) {
return Some(1); return Some(1);
}; };
if GARBAGE.contains(&name) { if GARBAGE.contains(&name) {