diff --git a/server/states/GoHomeState.js b/server/states/GoHomeState.js new file mode 100644 index 0000000..43e8c9b --- /dev/null +++ b/server/states/GoHomeState.js @@ -0,0 +1,89 @@ +/** + * GoHomeState - Navigate the turtle back to its home position + * After arrival, optionally transitions to dump inventory or another state + */ +import { BaseState } from './BaseState.js'; + +export class GoHomeState extends BaseState { + constructor(turtle, data = {}) { + super(turtle, data); + this.reason = data.reason || 'manual'; // 'low_fuel', 'inventory_full', 'too_far', 'manual' + this.returnState = data.returnState || null; // State to return to after going home + this.returnData = data.returnData || {}; + } + + get name() { + return 'returning'; + } + + get description() { + return `Returning home (${this.reason})`; + } + + async *act() { + const home = this.turtle.homePosition; + if (!home) { + console.log(`[${this.turtle.id}] No home position set, going idle`); + this.turtle.setState('idle'); + return; + } + + console.log(`[${this.turtle.id}] Going home: reason=${this.reason}`); + + // Navigate to home using D* Lite + const navGen = this.navigateTo(home, { canMine: true }); + for await (const _ of navGen) { + if (this.cancelled) return; + + // Check fuel during return + const fuel = await this.checkFuel(); + if (fuel !== 'unlimited' && fuel < 100) { + // Emergency refuel + await this.tryRefuel(); + } + + yield; + } + + // Arrived home + console.log(`[${this.turtle.id}] Arrived home`); + + // If we came home to dump inventory, do so + if (this.reason === 'inventory_full') { + this.turtle.setState('dumpInventory', { + returnState: this.returnState, + returnData: this.returnData, + }); + return; + } + + // If we came home to refuel, try refueling + if (this.reason === 'low_fuel') { + this.turtle.setState('refueling', { + returnState: this.returnState, + returnData: this.returnData, + }); + return; + } + + // If there's a return state, go to it + if (this.returnState) { + this.turtle.setState(this.returnState, this.returnData); + return; + } + + // Default: go idle + this.turtle.setState('idle'); + } + + getRecoveryData() { + return { + ...super.getRecoveryData(), + data: { + reason: this.reason, + returnState: this.returnState, + returnData: this.returnData, + }, + }; + } +}