import { Villager } from './routines.js'; /** * Environmental Interaction System for Villager AI * * This implementation handles how villagers interact with their environment, * including resource gathering and building usage. */ class EnvironmentInteractionSystem { constructor() { this.resources = new Map(); // Map of resource IDs to resource objects this.buildings = new Map(); // Map of building IDs to building objects } /** * Add a resource to the environment * @param {string} id - Resource identifier * @param {Resource} resource - Resource object */ addResource(id, resource) { this.resources.set(id, resource); } /** * Add a building to the environment * @param {string} id - Building identifier * @param {Building} building - Building object */ addBuilding(id, building) { this.buildings.set(id, building); } /** * Find the nearest resource of a specific type * @param {Array} position - Search position [x, y, z] * @param {string} type - Resource type * @returns {Resource|null} Nearest resource or null if none found */ findNearestResource(position, type) { let nearest = null; let minDistance = Infinity; for (const [id, resource] of this.resources) { if (resource.type === type && resource.amount > 0) { const distance = this.calculateDistance(position, resource.position); if (distance < minDistance) { minDistance = distance; nearest = resource; } } } return nearest; } /** * Find the nearest building of a specific type * @param {Array} position - Search position [x, y, z] * @param {string} type - Building type * @returns {Building|null} Nearest building or null if none found */ findNearestBuilding(position, type) { let nearest = null; let minDistance = Infinity; for (const [id, building] of this.buildings) { if (building.type === type) { const distance = this.calculateDistance(position, building.position); if (distance < minDistance) { minDistance = distance; nearest = building; } } } return nearest; } /** * Calculate distance between two points * @param {Array} pos1 - First position [x, y, z] * @param {Array} pos2 - Second position [x, y, z] * @returns {number} Distance between points */ calculateDistance(pos1, pos2) { return Math.sqrt( Math.pow(pos1[0] - pos2[0], 2) + Math.pow(pos1[1] - pos2[1], 2) + Math.pow(pos1[2] - pos2[2], 2) ); } /** * Gather a resource * @param {Villager} villager - Villager gathering the resource * @param {Resource} resource - Resource to gather * @returns {boolean} True if successful */ gatherResource(villager, resource) { if (!resource || resource.amount <= 0) return false; // Check if villager is close enough to gather if (this.calculateDistance(villager.position, resource.position) > resource.gatherRadius) { return false; } // Gather the resource const amount = Math.min(resource.gatherAmount, resource.amount); resource.amount -= amount; villager.inventory.add(resource.type, amount); return true; } /** * Use a building * @param {Villager} villager - Villager using the building * @param {Building} building - Building to use * @returns {boolean} True if successful */ useBuilding(villager, building) { if (!building) return false; // Check if villager is close enough to use if (this.calculateDistance(villager.position, building.position) > building.useRadius) { return false; } // Use the building return building.use(villager); } } /** * Resource class */ class Resource { constructor(id, type, position, amount, gatherRadius = 2, gatherAmount = 1) { this.id = id; this.type = type; // 'wood', 'stone', 'food', etc. this.position = position; this.amount = amount; this.gatherRadius = gatherRadius; this.gatherAmount = gatherAmount; } } /** * Building class */ class Building { constructor(id, type, position, useRadius = 3) { this.id = id; this.type = type; // 'house', 'workshop', 'market', etc. this.position = position; this.useRadius = useRadius; this.occupancy = 0; this.maxOccupancy = 1; } /** * Use the building * @param {Villager} villager - Villager using the building * @returns {boolean} True if successful */ use(villager) { if (this.occupancy >= this.maxOccupancy) return false; this.occupancy++; // Simulate building usage setTimeout(() => { this.occupancy--; }, 5000); // Occupied for 5 seconds return true; } } /** * Villager inventory system */ class Inventory { constructor() { this.items = new Map(); // Map of item types to quantities } /** * Add items to inventory * @param {string} type - Item type * @param {number} amount - Amount to add */ add(type, amount) { if (this.items.has(type)) { this.items.set(type, this.items.get(type) + amount); } else { this.items.set(type, amount); } } /** * Remove items from inventory * @param {string} type - Item type * @param {number} amount - Amount to remove * @returns {boolean} True if successful */ remove(type, amount) { if (!this.items.has(type)) return false; const current = this.items.get(type); if (current < amount) return false; this.items.set(type, current - amount); if (this.items.get(type) === 0) { this.items.delete(type); } return true; } /** * Get item count * @param {string} type - Item type * @returns {number} Item count */ getCount(type) { return this.items.get(type) || 0; } } // Add inventory to Villager class Villager.prototype.inventory = new Inventory(); export { EnvironmentInteractionSystem, Resource, Building, Inventory, Villager };