-
Notifications
You must be signed in to change notification settings - Fork 0
Description
/**
- ArgOS Demo Script
- Shows how to use the ArgOS framework to create and run simulations
*/
import {
createArgOSWorld,
runArgOSSimulation,
createAgent,
createEnvironmentalEntity,
Position,
SensoryData,
Memory,
Goals,
Actions,
CognitiveState,
Learning,
Social,
RealityFlux,
Environmental
} from './argos-framework.js';
import { ArgOSVisualizer } from './argos-visualization.js';
import { ArgOSAnalytics } from './argos-analytics.js';
// Global variables
let simulation = null;
let visualizer = null;
let analytics = null;
let running = false;
let stepInterval = null;
let isLearningEnabled = true;
let isSocialEnabled = true;
let isAnalyticsVisible = true;
/**
- Basic Demo - Creates a simple simulation with agents and environmental entities
*/
function runBasicDemo() {
console.log("Starting ArgOS Basic Demo...");
// Create the simulation world
simulation = createArgOSWorld();
// Add entities (10 agents, 20 resources, 10 obstacles, 5 hazards)
runArgOSSimulation(simulation, 10, 20, 10, 5, 0); // 0 steps - we'll step manually
// Set up visualization
visualizer = new ArgOSVisualizer('simulation-canvas', simulation.world);
visualizer.start();
// Set up analytics
analytics = new ArgOSAnalytics(simulation.world);
analytics.update();
updateAnalyticsDashboard();
// Reset controls state
running = false;
if (stepInterval) {
clearInterval(stepInterval);
stepInterval = null;
}
document.getElementById('run-button').textContent = 'Run';
// Update simulation info display
updateSimulationInfo(simulation.world);
}
/**
- Initialize the demo based on selected type
*/
function initDemo() {
const demoType = document.getElementById('demo-selector').value;
// Clear canvas and info panel
document.getElementById('simulation-canvas').getContext('2d').clearRect(
0, 0,
document.getElementById('simulation-canvas').width,
document.getElementById('simulation-canvas').height
);
document.getElementById('simulation-info').innerHTML = '';
// Stop running if active
if (running) {
clearInterval(stepInterval);
document.getElementById('run-button').textContent = 'Run';
running = false;
}
// Run selected demo
switch (demoType) {
case 'advanced':
runAdvancedDemo();
break;
case 'social':
runSocialDemo();
break;
case 'learning':
runLearningDemo();
break;
default:
runBasicDemo();
}
}
/**
- Initialize event handlers for all UI controls
*/
function initEventHandlers() {
// Demo selector
document.getElementById('demo-selector').addEventListener('change', initDemo);
// Step button
document.getElementById('step-button').addEventListener('click', () => {
stepSimulation();
});
// Run/Pause button
document.getElementById('run-button').addEventListener('click', () => {
toggleRunSimulation();
});
// Reset button
document.getElementById('reset-button').addEventListener('click', () => {
initDemo();
});
// Add agent button
document.getElementById('add-agent-button').addEventListener('click', () => {
addNewAgent();
});
// Add resource button
document.getElementById('add-resource-button').addEventListener('click', () => {
addNewResource();
});
// Reality bend button
document.getElementById('reality-bend-button').addEventListener('click', () => {
applyRealityBend();
});
// Major reality shift button
document.getElementById('reality-shift-button').addEventListener('click', () => {
triggerMajorRealityShift();
});
// Toggle learning button
document.getElementById('toggle-learning-button').addEventListener('click', () => {
toggleLearning();
});
// Toggle social button
document.getElementById('toggle-social-button').addEventListener('click', () => {
toggleSocial();
});
// Toggle analytics button
document.getElementById('toggle-analytics-button').addEventListener('click', () => {
toggleAnalytics();
});
// Export data button
document.getElementById('export-data-button').addEventListener('click', () => {
exportSimulationData();
});
}
/**
- Perform a single simulation step
*/
function stepSimulation() {
if (!simulation) return;
// Run all systems for one step
for (const system of simulation.systems) {
system(simulation.world);
}
// Update world time
simulation.world.time++;
// Update analytics
if (analytics) {
analytics.update();
if (isAnalyticsVisible) {
updateAnalyticsDashboard();
}
}
// Update simulation info display
updateSimulationInfo(simulation.world);
}
/**
- Toggle running/pausing the simulation
*/
function toggleRunSimulation() {
if (!simulation) return;
if (running) {
// Pause simulation
clearInterval(stepInterval);
document.getElementById('run-button').textContent = 'Run';
running = false;
} else {
// Run simulation
stepInterval = setInterval(() => {
stepSimulation();
}, 100); // 10 steps per second
document.getElementById('run-button').textContent = 'Pause';
running = true;
}
}
/**
- Add a new agent to the simulation
*/
function addNewAgent() {
if (!simulation) return;
// Create a new agent at a random position
createAgent(
simulation.world,
Math.random() * 100,
Math.random() * 100
);
// Immediately update displays
if (analytics) analytics.update();
updateSimulationInfo(simulation.world);
if (isAnalyticsVisible) updateAnalyticsDashboard();
}
/**
- Add a new resource to the simulation
*/
function addNewResource() {
if (!simulation) return;
// Create a new resource at a random position
createEnvironmentalEntity(
simulation.world,
Math.random() * 100,
Math.random() * 100,
0, // Resource type
50 + Math.floor(Math.random() * 50) // Value between 50-100
);
// Immediately update displays
if (analytics) analytics.update();
updateSimulationInfo(simulation.world);
if (isAnalyticsVisible) updateAnalyticsDashboard();
}
/**
- Apply a small reality bend to random entities
*/
function applyRealityBend() {
if (!simulation) return;
// Apply a reality bend to random entities
const numEntities = simulation.world.entities.length;
const numToAffect = Math.min(numEntities, 5);
for (let i = 0; i < numToAffect; i++) {
const entityIndex = Math.floor(Math.random() * numEntities);
// Skip if entity doesn't have reality flux component
if (!RealityFlux[entityIndex]) continue;
// Apply a random effect
const effectType = Math.floor(Math.random() * 3) + 1; // 1-3
RealityFlux.effectType[entityIndex] = effectType;
RealityFlux.duration[entityIndex] = 20 + Math.floor(Math.random() * 20); // 20-40 ticks
// Apply immediate effect based on type
switch (effectType) {
case 1: // Teleport
Position.x[entityIndex] = Math.random() * 100;
Position.y[entityIndex] = Math.random() * 100;
break;
case 2: // Phase - handled by renderer
break;
case 3: // Transform
if (Environmental[entityIndex]) {
// Change type randomly but ensure it's still 0-2
const currentType = Environmental.type[entityIndex];
let newType;
do {
newType = Math.floor(Math.random() * 3); // 0-2
} while(newType === currentType);
Environmental.type[entityIndex] = newType;
}
break;
}
}
// Immediately update displays
if (analytics) analytics.update();
updateSimulationInfo(simulation.world);
if (isAnalyticsVisible) updateAnalyticsDashboard();
}
/**
- Trigger a major reality shift with wave effect
*/
function triggerMajorRealityShift() {
if (!simulation) return;
console.log("Triggering major reality shift...");
// Create a reality wave
const randomDirection = Math.random() > 0.5 ? 'horizontal' : 'vertical';
simulation.world.realityWave = {
active: true,
x: randomDirection === 'horizontal' ? 0 : Math.random() * 100,
y: randomDirection === 'vertical' ? 0 : Math.random() * 100,
direction: randomDirection,
speed: 0.5 + Math.random() * 1.5, // 0.5 to 2.0
amplitude: 2 + Math.random() * 3, // 2 to 5
frequency: 0.05 + Math.random() * 0.1, // 0.05 to 0.15
particleCount: 10 + Math.floor(Math.random() * 20), // 10 to 30
particles: []
};
// Initialize wave particles
for (let i = 0; i < simulation.world.realityWave.particleCount; i++) {
simulation.world.realityWave.particles.push({
x: simulation.world.realityWave.x,
y: simulation.world.realityWave.y,
size: 1 + Math.random() * 3,
speed: 0.8 + Math.random() * 1.5,
angle: Math.random() * Math.PI * 2
});
}
// Apply shift effects to many entities
const fluxEntities = simulation.world.entities.filter(e => RealityFlux[e]);
for (let i = 0; i < fluxEntities.length; i++) {
const entity = fluxEntities[i];
const stability = RealityFlux.stability[entity];
// Higher chance of effect for this major shift
if (Math.random() * 150 > stability) {
const effectType = Math.floor(Math.random() * 3) + 1; // 1-3
RealityFlux.effectType[entity] = effectType;
RealityFlux.duration[entity] = 30 + Math.floor(Math.random() * 30); // 30-60 ticks
// Apply immediate effect
switch (effectType) {
case 1: // Teleport
Position.x[entity] = Math.random() * 100;
Position.y[entity] = Math.random() * 100;
break;
case 2: // Phase - handled by renderer
break;
case 3: // Transform
if (Environmental[entity]) {
// Change type randomly
Environmental.type[entity] = Math.floor(Math.random() * 3); // 0-2
}
break;
}
}
}
// Immediately update displays
if (analytics) analytics.update();
updateSimulationInfo(simulation.world);
if (isAnalyticsVisible) updateAnalyticsDashboard();
}
/**
- Toggle learning capabilities of agents
*/
function toggleLearning() {
isLearningEnabled = !isLearningEnabled;
// Update all agents' learning rates
for (let i = 0; i < simulation.world.entities.length; i++) {
if (Learning[i]) {
if (isLearningEnabled) {
Learning.learningRate[i] = 0.1; // Normal learning
Learning.explorationRate[i] = 0.2; // Normal exploration
} else {
Learning.learningRate[i] = 0.001; // Almost no learning
Learning.explorationRate[i] = 0.01; // Almost no exploration
}
}
}
// Update button text
document.getElementById('toggle-learning-button').textContent =
isLearningEnabled ? 'Disable Learning' : 'Enable Learning';
console.log(Learning ${isLearningEnabled ? 'enabled' : 'disabled'});
}
/**
- Toggle social capabilities of agents
*/
function toggleSocial() {
isSocialEnabled = !isSocialEnabled;
// Update all agents' social capabilities
for (let i = 0; i < simulation.world.entities.length; i++) {
if (Social[i]) {
if (isSocialEnabled) {
Social.trustLevel[i] = 70; // Normal trust level
} else {
Social.trustLevel[i] = 10; // Very low trust (prevents cooperation)
}
}
}
// Update button text
document.getElementById('toggle-social-button').textContent =
isSocialEnabled ? 'Disable Social' : 'Enable Social';
console.log(Social dynamics ${isSocialEnabled ? 'enabled' : 'disabled'});
}
/**
- Toggle analytics dashboard visibility
*/
function toggleAnalytics() {
isAnalyticsVisible = !isAnalyticsVisible;
// Show/hide analytics dashboard
document.getElementById('analytics-dashboard').style.display =
isAnalyticsVisible ? 'block' : 'none';
// Update button text
document.getElementById('toggle-analytics-button').textContent =
isAnalyticsVisible ? 'Hide Analytics' : 'Show Analytics';
}
/**
- Export simulation data as JSON
*/
function exportSimulationData() {
if (!analytics) return;
// Get data summary from analytics
const data = analytics.getDataSummary();
// Convert to JSON
const jsonData = JSON.stringify(data, null, 2);
// Create download link
const blob = new Blob([jsonData], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = argos-simulation-data-${Date.now()}.json;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
console.log('Simulation data exported');
}
/**
- Update the simulation information display
*/
function updateSimulationInfo(world) {
const infoPanel = document.getElementById('simulation-info');
// Count entities by type
let agentCount = 0;
let resourceCount = 0;
let obstacleCount = 0;
let hazardCount = 0;
for (let i = 0; i < world.entities.length; i++) {
if (SensoryData[i] && Memory[i] && Goals[i]) {
agentCount++;
}
if (Environmental[i]) {
switch (Environmental.type[i]) {
case 0: resourceCount++; break;
case 1: obstacleCount++; break;
case 2: hazardCount++; break;
}
}
}
// Generate HTML for info panel
const html = <h3>Simulation Information</h3> <p>Time: <span class="value">${world.time}</span></p> <p>Next Reality Shift: <span class="value">${150 - (world.time % 150)}</span> ticks</p> <h4>Entity Counts:</h4> <p>Agents: <span class="value">${agentCount}</span></p> <p>Resources: <span class="value">${resourceCount}</span></p> <p>Obstacles: <span class="value">${obstacleCount}</span></p> <p>Hazards: <span class="value">${hazardCount}</span></p> <h4>Status:</h4> <p>Learning: <span class="value">${isLearningEnabled ? 'Enabled' : 'Disabled'}</span></p> <p>Social: <span class="value">${isSocialEnabled ? 'Enabled' : 'Disabled'}</span></p> <h4>Selected Entity:</h4> <p>Click on an entity in the simulation to view details</p>;
infoPanel.innerHTML = html;
}
/**
- Update the analytics dashboard
*/
function updateAnalyticsDashboard() {
if (!analytics) return;
const container = document.getElementById('analytics-dashboard');
if (!container) return;
analytics.render(container);
}
/**
- Learning Agents Demo - Focuses on agents with enhanced learning capabilities
*/
function runLearningDemo() {
console.log("Starting ArgOS Learning Agents Demo...");
// Create the simulation world
simulation = createArgOSWorld();
const { world } = simulation;
// Create different types of learning agents
// Fast learners - high learning rate, low exploration
for (let i = 0; i < 5; i++) {
const entity = createAgent(world, 20 + i * 5, 20 + i * 5);
Learning.learningRate[entity] = 0.2; // Higher learning rate
Learning.explorationRate[entity] = 0.1; // Lower exploration (exploits more)
CognitiveState.adaptability[entity] = 90; // Very adaptable
}
// Explorers - medium learning rate, high exploration
for (let i = 0; i < 5; i++) {
const entity = createAgent(world, 50 + i * 5, 20 + i * 5);
Learning.learningRate[entity] = 0.1; // Medium learning rate
Learning.explorationRate[entity] = 0.4; // High exploration
CognitiveState.adaptability[entity] = 70; // Good adaptability
}
// Slow but steady - low learning rate, very low exploration
for (let i = 0; i < 5; i++) {
const entity = createAgent(world, 80 + i * 5, 80 + i * 5);
Learning.learningRate[entity] = 0.05; // Low learning rate
Learning.explorationRate[entity] = 0.05; // Very low exploration
CognitiveState.adaptability[entity] = 40; // Lower adaptability
}
// Create resources and hazards to learn about
for (let i = 0; i < 15; i++) {
createEnvironmentalEntity(
world,
10 + Math.random() * 80,
10 + Math.random() * 80,
0, // Resource
60 + Math.floor(Math.random() * 40)
);
}
for (let i = 0; i < 10; i++) {
createEnvironmentalEntity(
world,
10 + Math.random() * 80,
10 + Math.random() * 80,
2, // Hazard
70 + Math.floor(Math.random() * 30)
);
}
// Add some obstacles
for (let i = 0; i < 8; i++) {
createEnvironmentalEntity(
world,
10 + Math.random() * 80,
10 + Math.random() * 80,
1, // Obstacle
100
);
}
// Set up visualization
visualizer = new ArgOSVisualizer('simulation-canvas', world);
visualizer.start();
// Set up analytics
analytics = new ArgOSAnalytics(world);
analytics.update();
updateAnalyticsDashboard();
// Initial info update
updateSimulationInfo(world);
// Reset controls state
running = false;
if (stepInterval) {
clearInterval(stepInterval);
stepInterval = null;
}
document.getElementById('run-button').textContent = 'Run';
// Ensure learning is enabled
isLearningEnabled = true;
document.getElementById('toggle-learning-button').textContent = 'Disable Learning';
}
/**
- Social Dynamics Demo - Focuses on agent cooperation and group behavior
*/
function runSocialDemo() {
console.log("Starting ArgOS Social Dynamics Demo...");
// Create the simulation world
simulation = createArgOSWorld();
const { world } = simulation;
// Create groups of agents with different social characteristics
// Group 1: Highly cooperative (red group)
for (let i = 0; i < 5; i++) {
const entity = createAgent(world, 20 + i * 4, 20 + i * 4);
Social.groupId[entity] = 0; // Red group
Social.trustLevel[entity] = 90; // High trust
Goals.primaryType[entity] = 3; // Start with communication goal
}
// Group 2: Moderately cooperative (green group)
for (let i = 0; i < 5; i++) {
const entity = createAgent(world, 60 + i * 4, 20 + i * 4);
Social.groupId[entity] = 1; // Green group
Social.trustLevel[entity] = 70; // Medium trust
}
// Group 3: Independent/competitive (blue group)
for (let i = 0; i < 5; i++) {
const entity = createAgent(world, 40 + i * 4, 70 + i * 4);
Social.groupId[entity] = 2; // Blue group
Social.trustLevel[entity] = 30; // Low trust
CognitiveState.emotionalState[entity] = 30; // More cautious
}
// Add resources for agents to compete/cooperate over
for (let i = 0; i < 15; i++) {
createEnvironmentalEntity(
world,
10 + Math.random() * 80,
10 + Math.random() * 80,
0, // Resource
70 + Math.floor(Math.random() * 30) // High value resources
);
}
// Add obstacles and hazards for navigation challenges
for (let i = 0; i < 8; i++) {
createEnvironmentalEntity(
world,
10 + Math.random() * 80,
10 + Math.random() * 80,
1, // Obstacle
100
);
}
for (let i = 0; i < 5; i++) {
createEnvironmentalEntity(
world,
10 + Math.random() * 80,
10 + Math.random() * 80,
2, // Hazard
80
);
}
// Set up visualization
visualizer = new ArgOSVisualizer('simulation-canvas', world);
visualizer.start();
// Set up analytics
analytics = new ArgOSAnalytics(world);
analytics.update();
updateAnalyticsDashboard();
// Initial info update
updateSimulationInfo(world);
// Reset controls state
running = false;
if (stepInterval) {
clearInterval(stepInterval);
stepInterval = null;
}
document.getElementById('run-button').textContent = 'Run';
// Ensure social is enabled
isSocialEnabled = true;
document.getElementById('toggle-social-button').textContent = 'Disable Social';
}
/**
- Advanced Demo - Creates a more complex simulation with enhanced cognitive agents
- that have different learning rates and strategies
*/
function runAdvancedDemo() {
console.log("Starting ArgOS Advanced Demo...");
// Create the simulation world
simulation = createArgOSWorld();
const { world } = simulation;
// Create different types of agents with varying cognitive attributes
// Explorers - high adaptability, focus on discovering resources
for (let i = 0; i < 3; i++) {
const entity = createAgent(world, 10 + i * 5, 10 + i * 5);
CognitiveState.adaptability[entity] = 80 + Math.floor(Math.random() * 20); // High adaptability
CognitiveState.focus[entity] = 70 + Math.floor(Math.random() * 20); // High focus
CognitiveState.emotionalState[entity] = 70 + Math.floor(Math.random() * 20); // Bold
SensoryData.radius[entity] = 15; // Extended perception
Memory.capacity[entity] = 30; // Enhanced memory capacity
Learning.learningRate[entity] = 0.15;
Learning.explorationRate[entity] = 0.3;
Social.groupId[entity] = 0; // Red group
}
// Collectors - medium adaptability, focused on efficient resource gathering
for (let i = 0; i < 3; i++) {
const entity = createAgent(world, 30 + i * 5, 30 + i * 5);
CognitiveState.adaptability[entity] = 50 + Math.floor(Math.random() * 20); // Medium adaptability
CognitiveState.focus[entity] = 80 + Math.floor(Math.random() * 20); // Very high focus
CognitiveState.emotionalState[entity] = 40 + Math.floor(Math.random() * 20); // Neutral to cautious
Goals.primaryType[entity] = 1; // Start with collect goal
Goals.priority[entity] = 80; // High priority on collection
Learning.learningRate[entity] = 0.1;
Learning.explorationRate[entity] = 0.1;
Social.groupId[entity] = 1; // Green group
}
// Communicators - low adaptability but strong communication abilities
for (let i = 0; i < 3; i++) {
const entity = createAgent(world, 70 + i * 5, 70 + i * 5);
CognitiveState.adaptability[entity] = 30 + Math.floor(Math.random() * 20); // Low adaptability
CognitiveState.focus[entity] = 50 + Math.floor(Math.random() * 20); // Medium focus
CognitiveState.emotionalState[entity] = 60 + Math.floor(Math.random() * 20); // Neutral to bold
Communication.sending[entity] = 1; // Ready to communicate
SensoryData.radius[entity] = 12; // Good perception
Goals.primaryType[entity] = 3; // Start with communication goal
Learning.learningRate[entity] = 0.05;
Learning.explorationRate[entity] = 0.2;
Social.groupId[entity] = 2; // Blue group
Social.trustLevel[entity] = 90; // Very trusting
}
// Create environmental entities with different stability levels
// Stable resources - less affected by reality shifts
for (let i = 0; i < 10; i++) {
const entity = createEnvironmentalEntity(
world,
20 + Math.random() * 60,
20 + Math.random() * 60,
0, // Resource type
60 + Math.floor(Math.random() * 40) // Value between 60-100
);
RealityFlux.stability[entity] = 70 + Math.floor(Math.random() * 30); // High stability
}
// Unstable resources - highly affected by reality shifts
for (let i = 0; i < 5; i++) {
const entity = createEnvironmentalEntity(
world,
20 + Math.random() * 60,
20 + Math.random() * 60,
0, // Resource type
80 + Math.floor(Math.random() * 20) // High value between 80-100
);
RealityFlux.stability[entity] = 20 + Math.floor(Math.random() * 30); // Low stability
Environmental.value[entity] = 90; // High value resources
}
// Obstacles - mostly stable
for (let i = 0; i < 8; i++) {
const entity = createEnvironmentalEntity(
world,
10 + Math.random() * 80,
10 + Math.random() * 80,
1, // Obstacle type
100 // Full strength
);
RealityFlux.stability[entity] = 80 + Math.floor(Math.random() * 20); // Very stable
}
// Hazards - unstable and dangerous
for (let i = 0; i < 5; i++) {
const entity = createEnvironmentalEntity(
world,
20 + Math.random() * 60,
20 + Math.random() * 60,
2, // Hazard type
70 + Math.floor(Math.random() * 30) // Danger level between 70-100
);
RealityFlux.stability[entity] = 30 + Math.floor(Math.random() * 30); // Unstable
}
// Set up visualization
visualizer = new ArgOSVisualizer('simulation-canvas', world);
visualizer.start();
// Set up analytics
analytics = new ArgOSAnalytics(world);
analytics.update();
updateAnalyticsDashboard();
// Initial info update
updateSimulationInfo(world);
// Reset controls state
running = false;
if (stepInterval) {
clearInterval(stepInterval);
stepInterval = null;
}
document.getElementById('run-button').textContent = 'Run';
}
// Start the demo when the page loads
window.addEventListener('DOMContentLoaded', () => {
// Set up event handlers
initEventHandlers();
// Initialize with basic demo
runBasicDemo();
// Set initial states
isLearningEnabled = true;
isSocialEnabled = true;
isAnalyticsVisible = true;
// Set up button states
document.getElementById('toggle-learning-button').textContent = 'Disable Learning';
document.getElementById('toggle-social-button').textContent = 'Disable Social';
document.getElementById('toggle-analytics-button').textContent = 'Hide Analytics';
});