/** * MovingState - Navigate the turtle to a target position using D* Lite */ import { BaseState } from './BaseState.js'; export class MovingState extends BaseState { constructor(turtle, data = {}) { super(turtle, data); this.target = data.target; // {x, y, z} this.onArrival = data.onArrival || null; // Callback/next state when arrived this.canMine = data.canMine !== false; } get name() { return 'moving'; } get description() { const pos = this.target; if (pos) { return `Moving to (${pos.x}, ${pos.y}, ${pos.z})`; } return 'Moving to target'; } async *act() { if (!this.target) { console.log(`[${this.turtle.id}] MovingState: No target set`); this.turtle.setState('idle'); return; } console.log(`[${this.turtle.id}] Moving to ${this.target.x},${this.target.y},${this.target.z}`); // Use the navigateTo generator from BaseState const nav = this.navigateTo(this.target, { canMine: this.canMine }); for await (const _ of nav) { if (this.cancelled) return; yield; } // Check if we actually arrived const pos = this.turtle.position; if (pos) { const { Point } = await import('../pathfinding/index.js'); const current = Point.from(pos); const goal = Point.from(this.target); if (current.distanceTo(goal) <= 1) { console.log(`[${this.turtle.id}] Arrived at destination`); if (this.onArrival === 'idle') { this.turtle.setState('idle'); } else if (this.onArrival === 'mine') { this.turtle.setState('mining', this.data); } else { this.turtle.setState('idle'); } return; } } console.log(`[${this.turtle.id}] Failed to reach destination`); this.turtle.setState('idle'); } getRecoveryData() { return { ...super.getRecoveryData(), data: { target: this.target, onArrival: this.onArrival, canMine: this.canMine, }, }; } }