Spaces:
Running
Running
| /** | |
| * Daily Routine System for Villager AI (Simplified Version) | |
| * | |
| * This implementation manages villager daily routines including work, rest, and social interactions. | |
| * Uses simple arrays for positions instead of THREE.Vector3 to avoid import issues. | |
| */ | |
| class DailyRoutineManager { | |
| constructor() { | |
| this.schedules = new Map(); // Map of villager IDs to schedules | |
| this.currentTime = 0; // In-game time in hours (0-24) | |
| } | |
| /** | |
| * Set a schedule for a villager | |
| * @param {string} villagerId - Villager identifier | |
| * @param {Array} schedule - Array of schedule entries | |
| */ | |
| setSchedule(villagerId, schedule) { | |
| this.schedules.set(villagerId, schedule); | |
| } | |
| /** | |
| * Update the routine manager | |
| * @param {number} deltaTime - Time since last update in hours | |
| */ | |
| update(deltaTime) { | |
| this.currentTime += deltaTime; | |
| if (this.currentTime >= 24) { | |
| this.currentTime -= 24; // Wrap around to next day | |
| } | |
| } | |
| /** | |
| * Get current activity for a villager | |
| * @param {string} villagerId - Villager identifier | |
| * @returns {Object} Current activity | |
| */ | |
| getCurrentActivity(villagerId) { | |
| const schedule = this.schedules.get(villagerId); | |
| if (!schedule) return null; | |
| // Find the current activity based on time | |
| for (let i = schedule.length - 1; i >= 0; i--) { | |
| if (this.currentTime >= schedule[i].startTime) { | |
| return schedule[i]; | |
| } | |
| } | |
| // If no activity found, return the last one (for times before first activity) | |
| return schedule[schedule.length - 1]; | |
| } | |
| /** | |
| * Create a default schedule for a villager | |
| * @param {string} villagerId - Villager identifier | |
| * @param {Array} workLocation - Work location [x, y, z] | |
| * @param {Array} homeLocation - Home location [x, y, z] | |
| * @param {Array} socialLocations - Social locations [[x, y, z], ...] | |
| */ | |
| createDefaultSchedule(villagerId, workLocation, homeLocation, socialLocations) { | |
| const schedule = [ | |
| { startTime: 0, activity: 'sleep', location: homeLocation }, | |
| { startTime: 7, activity: 'eat', location: homeLocation }, | |
| { startTime: 8, activity: 'work', location: workLocation }, | |
| { startTime: 12, activity: 'eat', location: workLocation }, | |
| { startTime: 13, activity: 'work', location: workLocation }, | |
| { startTime: 17, activity: 'socialize', location: socialLocations[0] }, | |
| { startTime: 19, activity: 'eat', location: homeLocation }, | |
| { startTime: 20, activity: 'sleep', location: homeLocation } | |
| ]; | |
| this.setSchedule(villagerId, schedule); | |
| } | |
| } | |
| /** | |
| * Villager class with routine-based behavior (Simplified Version) | |
| */ | |
| class Villager { | |
| constructor(id, position) { | |
| this.id = id; | |
| this.position = position; // [x, y, z] array | |
| this.velocity = [0, 0, 0]; // [x, y, z] array | |
| this.maxSpeed = 2; | |
| this.energy = 100; | |
| this.hunger = 0; | |
| this.socialNeed = 0; | |
| this.state = 'idle'; // idle, working, sleeping, eating, socializing | |
| this.path = []; | |
| this.avoidanceRadius = 2; | |
| this.avoidanceWeight = 1.5; | |
| this.steeringWeight = 1.0; | |
| } | |
| /** | |
| * Update villager state | |
| * @param {DailyRoutineManager} routineManager - Routine manager | |
| * @param {VillagePathfinder} pathfinder - Pathfinding system | |
| * @param {number} deltaTime - Time since last update | |
| */ | |
| update(routineManager, pathfinder, deltaTime) { | |
| // Update needs | |
| this.updateNeeds(deltaTime); | |
| // Get current activity | |
| const activity = routineManager.getCurrentActivity(this.id); | |
| // Update state based on activity | |
| if (activity) { | |
| this.state = activity.activity; | |
| // If we have a location for this activity, pathfind to it | |
| if (activity.location && this.distanceTo(activity.location) > 1) { | |
| this.path = pathfinder.findPath(this.position, activity.location); | |
| } else { | |
| this.path = []; | |
| } | |
| } | |
| // Perform state-specific actions | |
| switch (this.state) { | |
| case 'sleep': | |
| this.sleep(deltaTime); | |
| break; | |
| case 'work': | |
| this.work(deltaTime); | |
| break; | |
| case 'eat': | |
| this.eat(deltaTime); | |
| break; | |
| case 'socialize': | |
| this.socialize(deltaTime); | |
| break; | |
| } | |
| } | |
| /** | |
| * Calculate distance to another position | |
| * @param {Array} other - Other position [x, y, z] | |
| * @returns {number} Distance | |
| */ | |
| distanceTo(other) { | |
| const dx = this.position[0] - other[0]; | |
| const dy = this.position[1] - other[1]; | |
| const dz = this.position[2] - other[2]; | |
| return Math.sqrt(dx * dx + dy * dy + dz * dz); | |
| } | |
| /** | |
| * Update villager needs over time | |
| * @param {number} deltaTime - Time since last update | |
| */ | |
| updateNeeds(deltaTime) { | |
| this.energy = Math.max(0, this.energy - 0.1 * deltaTime); | |
| this.hunger = Math.min(100, this.hunger + 0.05 * deltaTime); | |
| this.socialNeed = Math.min(100, this.socialNeed + 0.03 * deltaTime); | |
| } | |
| /** | |
| * Check if villager is tired | |
| * @returns {boolean} True if tired | |
| */ | |
| isTired() { | |
| return this.energy < 20; | |
| } | |
| /** | |
| * Check if villager should work | |
| * @returns {boolean} True if should work | |
| */ | |
| shouldWork() { | |
| return this.energy > 30 && this.hunger < 80; | |
| } | |
| /** | |
| * Check if villager should socialize | |
| * @returns {boolean} True if should socialize | |
| */ | |
| shouldSocialize() { | |
| return this.energy > 40 && this.socialNeed > 50; | |
| } | |
| /** | |
| * Sleep action | |
| * @param {number} deltaTime - Time since last update | |
| */ | |
| sleep(deltaTime) { | |
| this.energy = Math.min(100, this.energy + 0.5 * deltaTime); | |
| } | |
| /** | |
| * Work action | |
| * @param {number} deltaTime - Time since last update | |
| */ | |
| work(deltaTime) { | |
| this.energy = Math.max(0, this.energy - 0.2 * deltaTime); | |
| } | |
| /** | |
| * Eat action | |
| * @param {number} deltaTime - Time since last update | |
| */ | |
| eat(deltaTime) { | |
| this.hunger = Math.max(0, this.hunger - 0.8 * deltaTime); | |
| } | |
| /** | |
| * Socialize action | |
| * @param {number} deltaTime - Time since last update | |
| */ | |
| socialize(deltaTime) { | |
| this.socialNeed = Math.max(0, this.socialNeed - 0.6 * deltaTime); | |
| } | |
| /** | |
| * Idle action | |
| */ | |
| idle() { | |
| // Do nothing | |
| } | |
| } | |
| export { DailyRoutineManager, Villager }; |