Medieval-Village-AI / src /ai /environment.js
6rz6
Add Medieval Village AI Emulator
a32dc8b
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 };