diff --git a/demos/TREASURE_HUNT_SUMMARY.md b/demos/TREASURE_HUNT_SUMMARY.md
deleted file mode 100644
index af95643..0000000
--- a/demos/TREASURE_HUNT_SUMMARY.md
+++ /dev/null
@@ -1,434 +0,0 @@
-# Treasure Hunt Simulation - Project Summary
-
-## Overview
-
-This document summarizes the **Emergent Treasure Hunt** simulation, a sophisticated multi-agent AI system demonstrating collective intelligence through LLM-powered collaboration in NetLogo.
-
-## What It Is
-
-Five AI agents are trapped in a procedurally-generated maze. Each agent possesses only ONE clue about a hidden treasure's location and nature. No single agent can find the treasure alone. Through exploration, chance meetings, and LLM-mediated conversations, they must:
-
-1. **Share their fragmentary knowledge**
-2. **Synthesize collective understanding**
-3. **Build confidence in their conclusions**
-4. **Discover the treasure location**
-5. **Manifest the treasure through unified knowledge**
-
-## Key Features
-
-### ๐ค AI-Powered Agent Communication
-- Each agent maintains independent conversation history
-- Natural language knowledge exchange via `llm:chat`
-- Emergent insights beyond simple clue combination
-- Supports OpenAI, Claude, Gemini, and Ollama
-
-### ๐งฉ Emergent Problem-Solving
-- No hardcoded solutions
-- Treasure location discovered through agent collaboration
-- Different outcome each run due to:
- - Random maze generation
- - Random agent spawning
- - Stochastic exploration
- - LLM response variability
-
-### ๐จ Rich Visualization
-- **Agent size/brightness** increases with confidence
-- **Golden glow effects** when agents meet and communicate
-- **Colored trails** showing each agent's exploration path
-- **Pulsating treasure** with radiating light and sparkles
-- **Real-time plots** tracking confidence and knowledge accumulation
-
-### ๐ง Intelligent Behavior
-- Three exploration strategies: random, methodical, wall-follower
-- Goal-driven behavior: explore, find-center, find-crossing, search-systematically
-- LLM-based decision making for goals and location assessment
-- Adaptive confidence building
-
-## Implementation Architecture
-
-```
-โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-โ NetLogo Simulation โ
-โ โ
-โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
-โ โ Agent 0 โ โ Agent 1 โ โ Agent 2 โ โ
-โ โ Clue: โ โ Clue: โ โ Clue: โ ... โ
-โ โ "golden โ โ "paths โ โ "sum=15" โ โ
-โ โ & round" โ โ cross" โ โ โ โ
-โ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โ
-โ โ โ โ โ
-โ โโโโโโโโโโฌโโโโโโโโโดโโโโโโโโโฌโโโโโโโโโ โ
-โ โ โ โ
-โ โผ โผ โ
-โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
-โ โ LLM Extension Framework โ โ
-โ โ - Per-agent message history โ โ
-โ โ - llm:chat (synthesis) โ โ
-โ โ - llm:choose (selection) โ โ
-โ โ - Provider abstraction โ โ
-โ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโ โ
-โโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ
- โโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
- โ โ
- โโโโโโโผโโโโโโโ โโโโโโโผโโโโโโโ
- โ Cloud LLM โ โ Ollama โ
- โ Providers โ OR โ (Local) โ
- โ GPT/Claudeโ โ llama3.2 โ
- โโโโโโโโโโโโโโ โโโโโโโโโโโโโโ
-```
-
-## The Five Knowledge Fragments
-
-Each agent receives ONE clue:
-
-1. **Agent 0**: "The treasure is golden and round like the sun"
-2. **Agent 1**: "Look where two main paths cross each other"
-3. **Agent 2**: "The special place has coordinates that add up to exactly 15"
-4. **Agent 3**: "It only appears when all clues are combined"
-5. **Agent 4**: "Find the spot furthest from any wall"
-
-Only by combining these clues through LLM-synthesized conversations can the agents:
-- Understand the treasure's **appearance** (golden, round, sun-like)
-- Determine the **location type** (path crossing)
-- Calculate the **specific coordinates** (x + y = 15)
-- Recognize the **manifestation condition** (collective knowledge required)
-- Apply the **spatial constraint** (distance from walls)
-
-## How Collective Intelligence Emerges
-
-### Phase 1: Independent Exploration (Ticks 0-100)
-- Agents wander randomly using different strategies
-- No knowledge sharing yet
-- Confidence = 0 for all agents
-- Exploration marks patches as "visited"
-
-### Phase 2: Chance Encounters (Ticks 100-300)
-- Agents occasionally meet within communication range
-- First conversations exchange base clues
-- LLM synthesizes initial insights
-- Confidence begins to increase
-- Knowledge spreads like an epidemic
-
-### Phase 3: Accelerating Understanding (Ticks 300-600)
-- Agents now carry synthesized insights from multiple sources
-- Second-order knowledge sharing (AโB, BโC means C learns from A indirectly)
-- Goals shift from "explore" to "find-crossing" or "find-center"
-- Confidence accelerates exponentially
-- Visual effects intensify (larger, brighter agents)
-
-### Phase 4: Convergence & Discovery (Ticks 600+)
-- High-confidence agents actively search specific locations
-- Multiple agents may attempt manifestation at promising spots
-- LLM validates location based on accumulated knowledge
-- First agent with sufficient knowledge + confidence + correct location succeeds
-- Treasure manifests with celebration effects
-
-## Technical Highlights
-
-### LLM Integration Patterns
-
-**Pattern 1: Knowledge Synthesis**
-```netlogo
-let result llm:chat (word
- "I know: " my-clues
- ". Partner knows: " partner-clues
- ". What can we conclude about the treasure?")
-```
-- Both agents learn the synthesis
-- Creates emergent insights
-- Builds collective understanding
-
-**Pattern 2: Constrained Selection**
-```netlogo
-let goal llm:choose situation-description [
- "explore-more"
- "find-center"
- "find-crossing"
- "search-systematically"
-]
-```
-- Forces structured decision-making
-- Prevents hallucination
-- Guarantees valid action
-
-**Pattern 3: Location Validation**
-```netlogo
-let assessment llm:choose location-info [
- "yes-likely"
- "no-unlikely"
- "need-more-info"
-]
-```
-- LLM evaluates if current location matches clues
-- Combines spatial reasoning with NL understanding
-- Prevents premature treasure manifestation
-
-### Per-Agent Memory Management
-
-Each agent maintains separate conversation history:
-```
-Agent 0 history: ["golden and round", "Synthesis: might be a coin", ...]
-Agent 1 history: ["paths cross", "Synthesis: look for intersections", ...]
-Agent 2 history: ["sum=15", "Synthesis: check coordinates", ...]
-```
-
-This enables:
-- **Unique perspectives**: Same clue, different contexts
-- **Independent reasoning**: No cross-contamination
-- **Realistic communication**: Agents build on their own experience
-- **Efficient cleanup**: WeakHashMap removes history when agents die
-
-### Maze Generation Algorithm
-
-Uses **Recursive Backtracking** for perfect mazes:
-1. Start with all walls
-2. Carve passages from (1,1)
-3. Recursively visit unvisited neighbors
-4. Add meeting areas (3 open spaces)
-5. Add complexity (5 random path connections)
-
-Result: Challenging maze with guaranteed path between any two points.
-
-## Performance Optimization
-
-### Minimizing LLM Calls
-
-**Communication cooldown**: 5 ticks between conversations
-**Goal analysis threshold**: Only when confidence > 0.3 and learned-facts > 1
-**Location checking**: Only when goal = "search-systematically"
-
-Typical simulation: ~50-100 LLM calls total over 1000 ticks
-
-### Token Efficiency
-
-**Concise prompts**: Only essential context included
-**max_tokens=500**: Limits response length
-**Summarization**: Long histories compressed
-
-### Fallback Mechanisms
-
-Every LLM call has graceful degradation:
-```netlogo
-carefully [
- ; Try LLM operation
-] [
- ; Use simple heuristic if fails
-]
-```
-
-Ensures simulation never crashes due to:
-- API timeouts
-- Rate limits
-- Network issues
-- Invalid responses
-
-## Files Structure
-
-```
-demos/emergent-treasure-hunt/
-โโโ README.md # Overview and quick start
-โโโ USAGE_GUIDE.md # Complete user manual (troubleshooting, experiments)
-โโโ IMPLEMENTATION.md # Technical architecture and code walkthrough
-โโโ interface-widgets.md # Widget configuration reference
-โโโ hunter-model.nlogox # Main simulation (recommended)
-โโโ new-model.nlogox # Alternative version
-
-demos/
-โโโ config # LLM provider configuration
-```
-
-## Configuration
-
-Edit `demos/config` to choose your LLM provider:
-
-**Ollama (Free, Local, Recommended)**
-```ini
-provider=ollama
-model=llama3.2:latest
-base_url=http://localhost:11434
-```
-
-**OpenAI (Cloud)**
-```ini
-provider=openai
-api_key=sk-your-key-here
-model=gpt-4o-mini
-```
-
-**Claude (Cloud)**
-```ini
-provider=anthropic
-api_key=sk-ant-your-key-here
-model=claude-3-5-sonnet-20241022
-```
-
-**Gemini (Cloud)**
-```ini
-provider=gemini
-api_key=your-key-here
-model=gemini-1.5-flash
-```
-
-## Running the Simulation
-
-### Prerequisites
-1. NetLogo 7.0+ installed
-2. LLM Extension built and installed (see main README)
-3. LLM provider configured (Ollama is easiest)
-
-### Steps
-1. Open `demos/emergent-treasure-hunt/hunter-model.nlogox`
-2. Click **Setup** button (generates maze, creates agents)
-3. Click **Go** button (starts simulation)
-4. Watch as agents:
- - Explore the maze
- - Meet and communicate (golden glow)
- - Build confidence (grow larger/brighter)
- - Discover the treasure (pulsating golden orb)
-
-### Expected Timeline
-- **100-300 ticks**: First agent meetings
-- **300-600 ticks**: Knowledge spreading phase
-- **600-1000 ticks**: Treasure discovery (typical)
-- **1000+ ticks**: Rare, indicates configuration issues
-
-## Educational Value
-
-### Computer Science Concepts
-- **Multi-agent systems**: Coordination without central control
-- **Distributed problem-solving**: No agent has complete information
-- **Emergent behavior**: Complex outcomes from simple rules
-- **AI integration**: LLMs as reasoning engines
-- **Graph algorithms**: Maze generation and navigation
-
-### Cognitive Science
-- **Collective intelligence**: Groups solving problems individuals cannot
-- **Knowledge transfer**: Communication effectiveness
-- **Epistemic certainty**: Confidence building
-- **Spatial reasoning**: Location-based puzzle solving
-
-### Software Engineering
-- **Error handling**: Graceful degradation with fallbacks
-- **API integration**: Multiple provider support
-- **State management**: Per-agent conversation history
-- **Visualization**: Real-time feedback systems
-
-## Experimental Variations
-
-### Modify Communication Range
-```netlogo
-; Set to 1: Very limited, slower knowledge spread
-; Set to 5: Very broad, faster discovery
-communication-range = 2 ; Default
-```
-
-### Adjust Confidence Threshold
-```netlogo
-; Set to 0.5: Faster but less certain discovery
-; Set to 0.9: Slower but more thorough
-confidence-threshold = 0.7 ; Default
-```
-
-### Change Agent Count
-```netlogo
-; 2 agents: Minimal, very slow
-; 5 agents: Default, balanced
-; 10 agents: Fast, crowded
-num-hunters = 5
-```
-
-### Try Different Strategies
-- **random**: Unbiased exploration
-- **methodical**: Prefers unexplored areas
-- **wall-follower**: Systematic coverage
-- **mixed**: Each agent different (default)
-
-## Success Metrics
-
-### Knowledge Spread Rate
-Plot shows total learned facts over time:
-- **Slow rise**: Poor communication (increase range)
-- **Exponential rise**: Healthy spread
-- **Plateau**: All agents have shared maximum knowledge
-
-### Confidence Trajectory
-Plot shows average confidence over time:
-- **Stuck at 0**: Agents not meeting (increase range/count)
-- **Linear rise**: Steady knowledge accumulation
-- **Steep rise then plateau**: Approaching discovery
-
-### Discovery Time
-Time to treasure manifestation:
-- **< 500 ticks**: Very fast (check if too easy)
-- **500-1000 ticks**: Normal range
-- **> 1500 ticks**: Slow (check configuration)
-
-## Common Issues & Solutions
-
-### "Could not load config file"
-**Solution**: Verify `demos/config` exists, use absolute path
-
-### "LLM call failed"
-**Solution**: Check provider is running (Ollama) or API key valid
-
-### Agents not communicating
-**Solution**: Increase `communication-range` or `num-hunters`
-
-### Treasure never appears
-**Solution**: Lower `confidence-threshold`, increase timeout in config
-
-### Simulation too slow
-**Solution**: Use Ollama or GPT-4o-mini, reduce `max_tokens`, fewer agents
-
-## Future Enhancements
-
-### Agent Personalities
-Add traits: curious, cautious, analytical
-Modify LLM prompts based on personality
-
-### Dynamic Clue Generation
-Use LLM to create new clues each run
-
-### Competitive Agents
-Add greed parameter: willing to mislead others
-
-### Multiple Treasures
-Different clue sets lead to different treasures
-
-### Forgetting Mechanism
-Agents forget old facts, requiring refresh
-
-### Conversation Logging
-Track who talked to whom, analyze social network
-
-## Conclusion
-
-The Treasure Hunt simulation demonstrates that **sophisticated collective intelligence can emerge from simple per-agent rules combined with powerful language understanding**.
-
-Key insights:
-1. **No single agent succeeds alone** - collaboration is essential
-2. **LLMs enable rich reasoning** - not just clue concatenation
-3. **Emergent behavior is unpredictable** - different every time
-4. **Visualization matters** - seeing the story unfold enhances understanding
-5. **Robust design** - fallbacks ensure it always works
-
-This is not just a demoโit's a template for building complex AI multi-agent systems with NetLogo.
-
-## Documentation Quick Links
-
-- **[README.md](demos/emergent-treasure-hunt/README.md)** - Overview
-- **[USAGE_GUIDE.md](demos/emergent-treasure-hunt/USAGE_GUIDE.md)** - Complete instructions
-- **[IMPLEMENTATION.md](demos/emergent-treasure-hunt/IMPLEMENTATION.md)** - Technical details
-- **[Main LLM Extension Docs](docs/API-REFERENCE.md)** - API reference
-
-## Getting Help
-
-1. Read the USAGE_GUIDE.md for troubleshooting
-2. Check the IMPLEMENTATION.md for technical details
-3. Review the main LLM Extension documentation
-4. Open an issue on GitHub
-
----
-
-**Ready to explore collective intelligence? Open NetLogo and let the treasure hunt begin!**
diff --git a/demos/emergent-treasure-hunt/IMPLEMENTATION.md b/demos/emergent-treasure-hunt/IMPLEMENTATION.md
deleted file mode 100644
index a29dcb3..0000000
--- a/demos/emergent-treasure-hunt/IMPLEMENTATION.md
+++ /dev/null
@@ -1,696 +0,0 @@
-# Treasure Hunt - Technical Implementation Guide
-
-## Architecture Overview
-
-This document explains the technical implementation of the treasure hunt simulation, demonstrating how to build complex multi-agent AI systems with the NetLogo LLM Extension.
-
-## System Architecture
-
-```
-โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-โ NetLogo Environment โ
-โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
-โ โ Maze World (21x21) โ โ
-โ โ โโโโโโโโโโ โโโโโโโโโโ โโโโโโโโโโ โ โ
-โ โ โAgent 0 โ โAgent 1 โ โAgent 2 โ ... โ โ
-โ โ โClue A โ โClue B โ โClue C โ โ โ
-โ โ โโโโโฌโโโโโ โโโโโฌโโโโโ โโโโโฌโโโโโ โ โ
-โ โ โ โ โ โ โ
-โ โ โโโโโโโโโโโโโโดโโโโโโโโโโโโโ โ โ
-โ โ โ โ โ
-โ โ โผ โ โ
-โ โ โโโโโโโโโโโโโโโโโโโโโโโโ โ โ
-โ โ โ LLM Extension Core โ โ โ
-โ โ โ - Message History โ โ โ
-โ โ โ - Provider Factory โ โ โ
-โ โ โโโโโโโโโโโโฌโโโโโโโโโโโโ โ โ
-โ โโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
-โโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ
- โโโโโโโโโโโโดโโโโโโโโโโโ
- โ โ
- โโโโโโโผโโโโโโ โโโโโโโผโโโโโโ
- โ OpenAI โ โ Ollama โ
- โ Claude โ or โ (Local) โ
- โ Gemini โ โ โ
- โโโโโโโโโโโโโ โโโโโโโโโโโโโ
-```
-
-## Core Components
-
-### 1. World Structure
-
-**Global Variables**
-```netlogo
-globals [
- maze-width ; World width (21)
- maze-height ; World height (21)
- treasure-discovered? ; Boolean: has treasure been found
- treasure-definition ; String: LLM-generated description
- treasure-location ; Patch: where treasure manifested
- communication-pairs ; List: tracking agent meetings
-]
-```
-
-**Patch Properties**
-```netlogo
-patches-own [
- wall? ; Boolean: is this a wall
- explored? ; Boolean: has any agent visited
- meeting-glow ; Number: visual effect countdown
- path-color ; Color: base color for paths
-]
-```
-
-### 2. Agent Architecture
-
-**Agent State**
-```netlogo
-treasure-hunters-own [
- knowledge-fragment ; String: agent's initial clue
- learned-facts ; List[String]: accumulated insights
- current-goal ; String: current objective
- confidence-level ; Number 0-1: epistemic certainty
- last-communication ; Number: tick of last meeting
- exploration-strategy ; String: movement algorithm
- memory-trail ; List[Patch]: visited locations
-]
-```
-
-**Agent Lifecycle**
-```
-Setup Phase:
- โโ Spawn at random open patch
- โโ Assign unique knowledge fragment
- โโ Set exploration strategy
- โโ Initialize confidence = 0
- โโ Enable visual trail
-
-Main Loop (each tick):
- โโ move-through-maze()
- โโ detect-nearby-agents()
- โ โโ communicate-with(partner) [LLM]
- โโ analyze-current-situation() [LLM]
- โ โโ update current-goal
- โโ take-action-based-on-goal()
- โโ update-exploration-memory()
- โโ update-agent-appearance()
-```
-
-### 3. Maze Generation
-
-**Algorithm**: Recursive Backtracking
-```netlogo
-to generate-maze
- 1. Initialize all patches as walls
- 2. Start at patch (1, 1)
- 3. carve-maze-from(start-patch):
- - Mark current patch as path
- - Get unvisited neighbors (2 steps away)
- - For each random neighbor:
- * Carve path between current and neighbor
- * Recursively carve from neighbor
- 4. create-meeting-areas (3 open spaces)
- 5. add-maze-complexity (5 extra paths)
-end
-```
-
-**Result**: Perfect maze with multiple meeting areas and dead ends
-
-### 4. Exploration Strategies
-
-**Random**
-```netlogo
-if exploration-strategy = "random" [
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [ move-to one-of possible-moves ]
-]
-```
-
-**Methodical** (Prefers unexplored)
-```netlogo
-if exploration-strategy = "methodical" [
- let unexplored patches with [
- not wall? and not explored? and distance myself <= 1
- ]
- ifelse any? unexplored [
- move-to one-of unexplored
- ] [
- ; Fall back to random if all nearby explored
- move-to one-of patches with [not wall? and distance myself <= 1]
- ]
-]
-```
-
-**Wall-Follower** (Right-hand rule)
-```netlogo
-if exploration-strategy = "wall-follower" [
- right 90
- while [patch-ahead 1 = nobody or [wall?] of patch-ahead 1] [
- right 90
- ]
- let target-patch patch-ahead 1
- if target-patch != nobody and not [wall?] of target-patch [
- move-to target-patch
- ]
-]
-```
-
-### 5. Communication System
-
-**Detection Phase**
-```netlogo
-to detect-nearby-agents
- let nearby-hunters other treasure-hunters in-radius communication-range
-
- if any? nearby-hunters and (ticks - last-communication) > 5 [
- let communication-partner one-of nearby-hunters
-
- ; Visual effects
- ask patch-here [
- set meeting-glow 15
- set pcolor yellow
- ]
- ask patches in-radius 1.5 [
- if not wall? [
- set meeting-glow 8
- set pcolor yellow - 1
- ]
- ]
-
- ; Initiate conversation
- communicate-with communication-partner
- set last-communication ticks
- ]
-end
-```
-
-**Knowledge Exchange (LLM Integration)**
-```netlogo
-to communicate-with [partner]
- ; Prepare combined knowledge
- let my-info (word knowledge-fragment ". I have learned: " learned-facts)
- let partner-info (word [knowledge-fragment] of partner
- ". They have learned: " [learned-facts] of partner)
- let combined-info (word "I know: " my-info ". My partner knows: " partner-info)
-
- ; LLM synthesis
- carefully [
- set conversation-result llm:chat (word combined-info
- ". What can we conclude about finding a treasure? Give me new insights.")
-
- ; Both agents learn the same insight
- set learned-facts lput conversation-result learned-facts
- ask partner [
- set learned-facts lput conversation-result learned-facts
- ]
- ] [
- ; Fallback if LLM fails
- set conversation-result (word "Combining clues: " [knowledge-fragment] of partner)
- ]
-
- ; Update confidence
- set confidence-level confidence-level + 0.2
- if confidence-level > 1 [ set confidence-level 1 ]
-end
-```
-
-**Key Design Decisions:**
-- **Both agents learn**: Simulates true knowledge sharing
-- **LLM synthesis**: Creates emergent insights beyond simple concatenation
-- **Fallback mechanism**: Graceful degradation if LLM fails
-- **Cooldown period**: Prevents spam (5 tick minimum between communications)
-
-### 6. Goal-Driven Behavior
-
-**Situation Analysis**
-```netlogo
-to analyze-current-situation
- if length learned-facts > 1 and confidence-level > 0.3 [
- let situation-summary (word
- "My original clue: " knowledge-fragment
- ". What I've learned from others: " learned-facts
- ". I'm currently at coordinates " pxcor " " pycor
- ". What should be my next goal?")
-
- let possible-goals [
- "explore-more"
- "find-center"
- "find-crossing"
- "search-systematically"
- "gather-more-info"
- ]
-
- carefully [
- set current-goal llm:choose situation-summary possible-goals
- ] [
- ; Fallback to random
- set current-goal one-of possible-goals
- ]
- ]
-end
-```
-
-**Goal Execution**
-```netlogo
-to take-action-based-on-goal
- if current-goal = "find-center" [
- let center-patch patch (maze-width / 2) (maze-height / 2)
- if center-patch != nobody [ face center-patch ]
- ]
-
- if current-goal = "find-crossing" [
- let crossings patches with [not wall? and count neighbors with [not wall?] >= 3]
- if any? crossings [
- let nearest-crossing min-one-of crossings [distance myself]
- face nearest-crossing
- ]
- ]
-
- if current-goal = "search-systematically" [
- check-treasure-location
- ]
-end
-```
-
-### 7. Treasure Discovery Logic
-
-**Location Validation**
-```netlogo
-to check-treasure-location
- let location-matches? false
-
- if length learned-facts > 2 [
- let location-description (word
- "I am at coordinates " pxcor " " pycor
- ". The sum is " (pxcor + pycor)
- ". This location has " count neighbors with [not wall?] " open neighbors."
- ". Based on what I know: " learned-facts
- ". Could this be the treasure location?")
-
- carefully [
- let location-assessment llm:choose location-description
- ["yes-likely" "no-unlikely" "need-more-info"]
- if location-assessment = "yes-likely" [
- set location-matches? true
- ]
- ] [
- ; Fallback: hardcoded logic for clue "coordinates add to 15"
- if (pxcor + pycor) = 15 and count neighbors with [not wall?] >= 3 [
- set location-matches? true
- ]
- ]
- ]
-
- if location-matches? and confidence-level > confidence-threshold [
- attempt-treasure-manifestation
- ]
-end
-```
-
-**Manifestation Process**
-```netlogo
-to attempt-treasure-manifestation
- if not treasure-discovered? [
- ; Collect ALL knowledge from ALL agents
- let all-knowledge []
- ask treasure-hunters [
- set all-knowledge lput knowledge-fragment all-knowledge
- set all-knowledge sentence all-knowledge learned-facts
- ]
-
- let combined-knowledge reduce word all-knowledge
-
- ; LLM generates treasure description
- carefully [
- let treasure-description llm:chat (word
- "Based on all our clues: " combined-knowledge
- ". What exactly is the treasure and what does it look like?")
-
- if length treasure-description > 10 [
- set treasure-definition treasure-description
- set treasure-location patch-here
- manifest-treasure
- ]
- ] [
- ; Fallback treasure
- if length all-knowledge > 4 [
- set treasure-definition "A glowing golden orb that brings joy"
- set treasure-location patch-here
- manifest-treasure
- ]
- ]
- ]
-end
-```
-
-### 8. Visual Effects System
-
-**Agent Visualization**
-```netlogo
-to update-agent-appearance
- ; Size increases with confidence
- set size (0.9 + 0.4 * confidence-level)
-
- ; Brightness increases with confidence
- if confidence-level > 0.5 [
- set color (base-color + 2)
- ]
-
- ; High-confidence agents get halo effect
- if confidence-level > 0.8 [
- ask patches in-radius 1 [
- if not wall? and meeting-glow <= 0 [
- set pcolor (pcolor + 0.5)
- ]
- ]
- ]
-end
-```
-
-**Communication Effects**
-```netlogo
-; Meeting glow decay
-to update-visual-effects
- ask patches with [meeting-glow > 0] [
- set meeting-glow meeting-glow - 1
- if meeting-glow <= 0 [
- set pcolor path-color
- if explored? [ set pcolor path-color + 0.5 ]
- ]
- ]
-end
-```
-
-**Treasure Animation**
-```netlogo
-; Pulsating treasure
-ask treasures [
- set glow-phase glow-phase + 0.3
- set color (yellow + 2 + 2 * sin(glow-phase * 180))
- set size (1.2 + 0.3 * sin(glow-phase * 90))
-
- ; Radiating light
- ask patches in-radius 2 [
- if not wall? [
- let distance-from-treasure distance myself
- let glow-intensity (3 - distance-from-treasure) / 3
- set pcolor (yellow + glow-intensity * 2)
- ]
- ]
-
- ; Sparkles
- if random 10 < 3 [
- ask one-of patches in-radius 1.5 with [not wall?] [
- set pcolor white
- set meeting-glow 3
- ]
- ]
-]
-```
-
-## LLM Integration Patterns
-
-### Pattern 1: Synchronous Knowledge Synthesis
-
-**Use Case**: Agent-to-agent knowledge exchange
-
-```netlogo
-let result llm:chat prompt
-; Blocks until LLM responds
-; Agent waits, then uses result
-```
-
-**Pros**:
-- Simple, sequential logic
-- Guaranteed result before proceeding
-
-**Cons**:
-- Blocks agent during LLM call
-- Can slow simulation
-
-### Pattern 2: Constrained Selection
-
-**Use Case**: Choosing from predefined options
-
-```netlogo
-let choice llm:choose description options
-; LLM must pick from provided list
-```
-
-**Pros**:
-- Guaranteed valid output
-- Prevents hallucination
-- Forces structured thinking
-
-**Cons**:
-- Limited to predefined choices
-- May miss creative solutions
-
-### Pattern 3: Asynchronous Processing (Not currently used)
-
-**Potential Enhancement**:
-```netlogo
-; Start LLM call without blocking
-let awaitable llm:chat-async prompt
-
-; Do other work
-move-through-maze
-update-visual-effects
-
-; Get result when needed
-let result runresult awaitable
-```
-
-**Benefits**:
-- Agents continue moving during LLM calls
-- Better performance
-- More realistic parallelism
-
-## Performance Considerations
-
-### LLM Call Frequency
-
-Current design limits LLM calls:
-- **Communication**: Once per 5 ticks per pair
-- **Goal analysis**: Only when confidence > 0.3 and learned-facts > 1
-- **Location check**: Only when goal = "search-systematically"
-
-### Token Optimization
-
-Prompts are kept concise:
-- Use `max_tokens=500` in config
-- Summarize instead of full context
-- Combine related queries
-
-### Fallback Mechanisms
-
-Every LLM call has fallback:
-```netlogo
-carefully [
- ; Try LLM operation
-] [
- ; Use simple heuristic if fails
-]
-```
-
-## Emergent Properties
-
-### Knowledge Propagation
-
-Knowledge spreads like an epidemic:
-1. Agent A meets Agent B
-2. Both synthesize new insight
-3. Agent A meets Agent C (shares A+B knowledge)
-4. Agent B meets Agent D (shares A+B knowledge)
-5. Exponential growth of collective knowledge
-
-### Spatial Clustering
-
-Agents naturally cluster:
-- Meeting areas become hot spots
-- Agents with similar goals converge
-- High-traffic areas explored more
-
-### Confidence Cascades
-
-Confidence builds collectively:
-- Initial meetings: Low confidence
-- Middle phase: Accelerating confidence
-- Late phase: High confidence everywhere
-
-### Goal Synchronization
-
-Agents' goals tend to align:
-- Early: All "explore-more"
-- Middle: Mix of goals based on knowledge
-- Late: Many "search-systematically"
-
-## Testing Strategy
-
-### Unit Tests
-
-Test individual components:
-```netlogo
-; Test maze generation
-setup
-assert [ count patches with [wall?] > 0 ]
-assert [ count patches with [not wall?] > 0 ]
-
-; Test agent creation
-assert [ count treasure-hunters = num-hunters ]
-assert [ all? treasure-hunters [knowledge-fragment != ""] ]
-```
-
-### Integration Tests
-
-Test LLM integration:
-```netlogo
-; Test communication
-setup
-ask one-of treasure-hunters [
- let partner one-of other treasure-hunters
- communicate-with partner
- assert [ length learned-facts > 0 ]
-]
-```
-
-### End-to-End Tests
-
-Run full simulation:
-```netlogo
-setup
-repeat 1000 [ go ]
-assert [ treasure-discovered? or ticks >= 1000 ]
-```
-
-## Extension Ideas
-
-### 1. Agent Personalities
-
-Add personality traits affecting LLM prompts:
-```netlogo
-treasure-hunters-own [
- ...
- personality ; "curious", "skeptical", "impulsive"
-]
-
-; Modify prompts
-llm:chat (word "As a " personality " hunter, " ...)
-```
-
-### 2. Dynamic Clues
-
-Generate clues with LLM at setup:
-```netlogo
-to-report generate-clue [treasure-location]
- let clue llm:chat (word
- "Create a cryptic clue hinting at location " treasure-location
- ". Be poetic and mysterious.")
- report clue
-end
-```
-
-### 3. Agent Competition
-
-Add competitive element:
-```netlogo
-treasure-hunters-own [
- ...
- treasure-greed ; Higher = less willing to share
-]
-
-; In communicate-with:
-if treasure-greed < 0.5 [
- ; Share knowledge
-] else [
- ; Share partial knowledge or mislead
-]
-```
-
-### 4. Multi-Treasure Hunt
-
-Multiple treasures requiring different clue combinations:
-```netlogo
-globals [
- treasure-type ; "golden-orb", "ancient-scroll", "crystal-gem"
-]
-
-; Each agent knows clues for different treasures
-; Must figure out which clues go together
-```
-
-### 5. Memory Limits
-
-Add forgetting mechanism:
-```netlogo
-to update-learned-facts
- ; Keep only last N facts
- if length learned-facts > memory-capacity [
- set learned-facts sublist learned-facts 1 (memory-capacity + 1)
- ]
-end
-```
-
-### 6. Conversation History
-
-Track specific conversations:
-```netlogo
-treasure-hunters-own [
- ...
- conversation-partners ; List of agents talked to
-]
-
-; Use in prompts
-llm:chat (word "You've talked to agents " conversation-partners "...")
-```
-
-## Debugging Tips
-
-### Enable Verbose Logging
-
-```netlogo
-; In communicate-with
-print (word "=== AGENT INTERACTION at tick " ticks " ===")
-print (word "Hunter " who " meets Hunter " [who] of partner)
-print (word "Location: (" pxcor ", " pycor ")")
-print (word "LLM Response: " conversation-result)
-```
-
-### Visualize Internal State
-
-```netlogo
-; Add monitor for specific agent
-ask turtle 0 [
- print (word "Confidence: " confidence-level)
- print (word "Goal: " current-goal)
- print (word "Learned: " learned-facts)
-]
-```
-
-### Test LLM Directly
-
-```netlogo
-; In NetLogo command center
-llm:set-provider "ollama"
-llm:set-model "llama3.2:latest"
-print llm:chat "Test message"
-```
-
-## Conclusion
-
-This implementation demonstrates:
-- **Multi-agent coordination** through LLM-mediated communication
-- **Emergent problem-solving** from simple interaction rules
-- **Spatial reasoning** combined with natural language understanding
-- **Robust error handling** with fallback mechanisms
-- **Rich visualization** showing internal agent states
-
-The key insight: **Complex collective intelligence emerges from simple per-agent rules + powerful language understanding.**
-
-## Further Resources
-
-- [NetLogo Dictionary](https://ccl.northwestern.edu/netlogo/docs/dictionary.html)
-- [LLM Extension API](../../docs/API-REFERENCE.md)
-- [Multi-Agent Systems](https://www.cs.ox.ac.uk/people/michael.wooldridge/pubs/imas/)
-- [Emergent Behavior in NetLogo](http://ccl.northwestern.edu/netlogo/models/community/)
diff --git a/demos/emergent-treasure-hunt/IMPROVEMENTS.md b/demos/emergent-treasure-hunt/IMPROVEMENTS.md
deleted file mode 100644
index cb83b2e..0000000
--- a/demos/emergent-treasure-hunt/IMPROVEMENTS.md
+++ /dev/null
@@ -1,389 +0,0 @@
-# Treasure Hunt Improvements
-
-## Overview
-
-The improved version (`treasure-hunt-improved.nlogox`) fixes critical convergence issues in the original model while keeping LLM-driven collaborative solving at the core.
-
----
-
-## ๐ฏ Problems Fixed
-
-### **Problem #1: Knowledge Fragmentation**
-**Original:** When Agent A met Agent B, they created a synthesis, but Agent A's previous knowledge wasn't shared with B.
-
-**Example:**
-```
-Agent A has: ["clue1", "insight from meeting C"]
-Agent B has: ["clue2"]
-They meet โ create "insight_AB"
-
-Result:
-Agent A: ["clue1", "insight from C", "insight_AB"]
-Agent B: ["clue2", "insight_AB"] โ Missing "insight from C"!
-```
-
-**Fix:** Complete knowledge transfer
-```netlogo
-; BOTH agents get EVERYTHING
-let combined-facts sentence my-learned partner-learned
-set combined-facts lput synthesis combined-facts
-
-set learned-facts combined-facts ; Agent A
-ask partner [
- set learned-facts combined-facts ; Agent B gets same
-]
-```
-
-**Result:** After meeting, both agents have 100% identical knowledge. No fragmentation!
-
----
-
-### **Problem #2: Vague LLM Responses**
-**Original:** Prompts like "What can we conclude?" got vague responses like "Work together to find it."
-
-**Fix:** Structured prompts with format requirements
-```netlogo
-let synthesis-prompt (word
- "You are analyzing treasure hunt clues. Be SPECIFIC and CONCRETE.\n\n"
- "AGENT 1 KNOWS:\n"
- "- Original clue: \"" my-clue "\"\n"
- "- Learned facts: " my-learned "\n\n"
-
- "TASK: Synthesize ONE specific insight about:\n"
- "1. Physical appearance (golden/round/glowing)\n"
- "2. Location criteria (coordinates/intersections/walls)\n\n"
-
- "FORMAT: 'The treasure [appearance] located at/where [specific location with numbers].'\n\n"
-
- "GOOD: 'The treasure is a golden sphere located where coordinates sum to 15.'\n"
- "BAD: 'Work together to find it.'\n\n"
-
- "Your synthesis:"
-)
-```
-
-**Result:** LLM gets clear instructions, examples, and required format โ much better responses!
-
----
-
-### **Problem #3: Random Goal Selection**
-**Original:** LLM picked goals randomly - might never choose "search-systematically"
-
-**Fix:** Deterministic progression based on confidence
-```netlogo
-to analyze-current-situation
- if confidence-level < 0.4 [
- set current-goal "explore"
- ]
-
- if confidence-level >= 0.4 and confidence-level < 0.7 [
- set current-goal "find-crossing"
- ]
-
- if confidence-level >= 0.7 [
- set current-goal "search-systematically"
- ]
-end
-```
-
-**Result:**
-- 0-2 meetings โ explore (build knowledge)
-- 2-3 meetings โ seek crossings (directed search)
-- 4+ meetings โ systematic checking (find treasure)
-- **GUARANTEED** progression!
-
----
-
-### **Problem #4: Hardcoded Fallback**
-**Original:** Fallback checked `if (x+y) = 15 and intersection`, which hardcodes the answer
-
-**Fix:** Pattern-based validation
-```netlogo
-; Check if knowledge MENTIONS sum/coordinates
-let mentions-sum? false
-foreach learned-facts [ fact ->
- if member? "sum" fact or member? "15" fact or member? "coordinate" fact [
- set mentions-sum? true
- ]
-]
-
-; Only then check if THIS location's sum is reasonable
-if mentions-sum? [
- if pxcor + pycor >= 12 and pxcor + pycor <= 18 [
- score += 1 ; Promising
- ]
-]
-```
-
-**Result:** Checks patterns learned, not exact answer. Works with different clue sets!
-
----
-
-### **Problem #5: Confidence Without Knowledge**
-**Original:** Confidence increased even with useless LLM responses
-
-**Fix:** Validate response quality before accepting
-```netlogo
-; Check for useful keywords
-let is-useful? false
-if length synthesis >= 20 [
- if (member? "golden" synthesis or member? "round" synthesis or
- member? "intersection" synthesis or member? "15" synthesis or ...) [
- set is-useful? true
- ]
-]
-
-if is-useful? [
- ; Accept and increase confidence
- set confidence-level confidence-level + 0.2
-] else [
- ; Reject vague response, minimal confidence gain
- print "โ Vague response ignored"
-]
-```
-
-**Result:** Confidence only builds with real knowledge!
-
----
-
-### **Problem #6: Isolated Agents**
-**Original:** Agents in separate maze areas might never meet
-
-**Fix:** Periodic knowledge broadcast
-```netlogo
-to go
- ; ... existing code ...
-
- ; Every 100 ticks, share widely
- if ticks mod 100 = 0 [
- broadcast-knowledge
- ]
-end
-
-to broadcast-knowledge
- ask treasure-hunters with [confidence-level >= 0.5] [
- let listeners other treasure-hunters in-radius 5 ; Larger radius
-
- ask listeners [
- ; Merge knowledge
- foreach [learned-facts] of myself [ fact ->
- if not member? fact learned-facts [
- set learned-facts lput fact learned-facts
- ]
- ]
-
- ; Small boost (less than direct meeting)
- set confidence-level confidence-level + 0.05
- ]
- ]
-end
-```
-
-**Result:** Even isolated agents eventually get knowledge. Guaranteed coverage!
-
----
-
-## ๐ Convergence Comparison
-
-| Metric | Original | Improved |
-|--------|----------|----------|
-| **Knowledge spread** | Fragmented | Complete |
-| **Goal progression** | Random (LLM) | Deterministic |
-| **Confidence reliability** | Unreliable | Validated |
-| **LLM dependency** | Critical path | Optional flavor |
-| **Convergence guarantee** | โ None | โ
Mathematical |
-| **Typical time to treasure** | 800-1500 ticks | 500-800 ticks |
-| **Failure rate** | ~30% | <5% |
-
----
-
-## ๐ What You'll See
-
-### **Console Output Improvements**
-
-**Original:**
-```
-=== AGENT INTERACTION ===
-Hunter 0 meets Hunter 1
-LLM Response: You should work together.
-Confidence: 0.2
-```
-
-**Improved:**
-```
-=== MEETING at tick 47 ===
-Hunter 0 โ Hunter 1
-Location: (8, 7)
-Consulting LLM...
-LLM: The treasure is a golden sphere located where coordinates sum to 15 at a path intersection.
-โ Useful knowledge gained!
- Confidence: 0.20 | Knowledge count: 1
-Hunter 0 goal: 'explore' โ 'explore' (confidence: 0.20)
-================================
-```
-
-### **Behavior Differences**
-
-**Original:**
-- Agents might stay at low confidence forever
-- Goals change unpredictably
-- Some agents isolated with no knowledge
-- Treasure might manifest at wrong location (fallback)
-
-**Improved:**
-- Confidence steadily builds to 0.7+
-- Clear progression: explore โ find-crossing โ search-systematically
-- Broadcasts prevent isolation
-- Location validation robust (LLM + fallback)
-
----
-
-## ๐ฎ How to Use
-
-1. **Open** `treasure-hunt-improved.nlogox` in NetLogo
-2. **Click Setup** - Loads LLM config, generates maze, spawns 5 agents
-3. **Click Go** - Watch the improved convergence
-
-### **What to Watch For:**
-
-**Ticks 0-100:** Random exploration
-- Agents wander
-- First meetings with structured prompts
-- Knowledge quality validation visible in console
-
-**Ticks 100-300:** Knowledge spreading
-- "โ Useful knowledge gained!" messages
-- Agents getting identical knowledge
-- Confidence building steadily
-
-**Ticks 300-500:** Behavior shifts
-- Agents changing goals based on confidence
-- "goal: 'explore' โ 'find-crossing'" messages
-- Movement toward intersections visible
-
-**Ticks 500-800:** Convergence
-- Multiple agents with confidence 0.7+
-- "search-systematically" goal active
-- Location checking attempts
-- **TREASURE MANIFESTS!**
-
----
-
-## ๐ก Key Insights
-
-### **1. LLM Still Central, But Not Critical**
-- LLM drives knowledge synthesis (the interesting part)
-- But failures don't break convergence
-- Fallbacks are intelligent, not hardcoded
-
-### **2. Deterministic + Stochastic Hybrid**
-- Random: maze, spawn, meetings
-- Deterministic: goals, knowledge transfer
-- LLM: creative synthesis
-- **Result:** Predictable convergence with interesting variation
-
-### **3. Visible Learning**
-- Console shows quality validation
-- Agent size/brightness reflects confidence
-- Goal changes explicit
-- Knowledge count tracked in plot
-
-### **4. Guaranteed Convergence**
-```
-Knowledge spreads (complete transfer + broadcasts)
- โ
-Confidence builds (only with quality knowledge)
- โ
-Goals progress (deterministic thresholds)
- โ
-Location checking (multiple agents, robust validation)
- โ
-TREASURE FOUND (mathematical certainty)
-```
-
----
-
-## ๐งช Testing Recommendations
-
-### **Test 1: Quality Validation**
-1. Run with a poor LLM model (or high temperature)
-2. Watch console for "โ Vague response ignored"
-3. Verify confidence still builds (just slower)
-4. Treasure should still manifest
-
-### **Test 2: Isolated Agents**
-1. Set `communication-range` to 1 (very small)
-2. Watch for broadcast messages every 100 ticks
-3. Verify knowledge spreads even without direct meetings
-4. Convergence should still occur (just slower)
-
-### **Test 3: Goal Progression**
-1. Watch console for goal changes
-2. Verify pattern: explore โ find-crossing โ search-systematically
-3. Check agents with confidence 0.7+ all have search-systematically
-4. Should be deterministic (no randomness)
-
-### **Test 4: Complete Knowledge Transfer**
-1. After agents meet, check their knowledge counts
-2. Should be identical
-3. "Knowledge count: N" should match for both
-4. No fragmentation
-
----
-
-## ๐ Performance Characteristics
-
-### **Time Complexity**
-- Original: O(unpredictable) - might never converge
-- Improved: O(nยฒ) where n = num-hunters
- - Knowledge spreads in log(n) meetings
- - Each agent checks locations systematically
- - Broadcasts ensure O(1) minimum progress
-
-### **LLM Call Frequency**
-- Communication: ~1 call per 6 ticks (cooldown)
-- Goal analysis: REMOVED (was 1 call per agent per tick if confident)
-- Location check: ~1 call per agent per tick if searching
-- Treasure description: 1 call total
-- **Total reduction:** ~60% fewer LLM calls
-
-### **Memory Usage**
-- Learned facts: Unbounded growth (but deduplicated)
-- After 10 meetings: ~10 unique facts per agent
-- Broadcasts share facts without duplication
-- Memory-efficient knowledge representation
-
----
-
-## ๐ฎ Future Enhancements
-
-### **Easy Wins:**
-1. Add confidence decay (agents forget if no meetings)
-2. Add agent personalities (cautious, adventurous)
-3. Limit learned-facts size (keep top N most relevant)
-
-### **Medium Effort:**
-1. Use `llm:chat-async` for parallel LLM calls
-2. Add conversation memory between specific pairs
-3. Temperature adjustment based on confidence
-
-### **Advanced:**
-1. Dynamic clue generation (LLM creates puzzle each run)
-2. Multi-treasure hunts (different clue combinations)
-3. Competitive agents (share or hoard knowledge)
-
----
-
-## ๐ Summary
-
-The improved model maintains the **LLM-driven collaborative solving** that makes the simulation interesting, while adding **deterministic convergence mechanisms** that make it reliable.
-
-**Result:** Best of both worlds!
-- โ
Agents visibly learn and improve
-- โ
LLM creates interesting syntheses
-- โ
Guaranteed convergence in <1000 ticks
-- โ
Robust to LLM failures
-- โ
Observable emergent behavior
-- โ
Simple, clean implementation
-
-**Try it and watch the improved convergence!**
diff --git a/demos/emergent-treasure-hunt/README.md b/demos/emergent-treasure-hunt/README.md
deleted file mode 100644
index 758a1f6..0000000
--- a/demos/emergent-treasure-hunt/README.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Emergent Treasure Hunt Demo
-
-## The Story
-
-**"The Collective Mystery of the Lost Treasure"**
-
-This NetLogo simulation tells the story of emergent collective intelligence through a treasure hunting adventure that unfolds in four dramatic acts:
-
-### Act I: The Scattered Knowledge
-Five treasure hunters find themselves lost in an ancient maze, each carrying only a fragment of the complete treasure mystery:
-- *"The treasure is golden and round like the sun"*
-- *"Look where two main paths cross each other"*
-- *"The special place has coordinates that add up to exactly 15"*
-- *"It only appears when all clues are combined"*
-- *"Find the spot furthest from any wall"*
-
-### Act II: The Wandering and Meetings
-The hunters explore using different strategies, leaving colorful trails. When they meet, golden light spreads between them as they share knowledge through LLM-powered conversations. Their confidence grows visibly as they learn from each other.
-
-### Act III: The Revelation
-As collective understanding emerges, agents develop new goals and search strategies based on their synthesized knowledge, demonstrating collaborative problem-solving.
-
-### Act IV: The Manifestation
-When sufficient knowledge combines at the right location with enough confidence, the treasure materializes as a pulsating golden orb surrounded by dancing sparkles.
-
-## The Deeper Meaning
-
-This simulation demonstrates how **no single individual has the complete picture**, but through **communication, trust, and collective reasoning**, groups can solve mysteries impossible for individuals alone. It's a metaphor for scientific discovery, community problem-solving, and the power of shared knowledge.
-
-## Visual Features
-
-- **Agent Visualization**: Size and brightness increase with confidence level
-- **Communication Effects**: Golden spreading patterns when agents meet and share knowledge
-- **Treasure Animation**: Pulsating golden orb with radiating light and sparkle effects
-- **Trail System**: Colorful paths showing each agent's unique exploration journey
-- **Maze Environment**: Procedurally generated using recursive backtracking algorithm
-
-## Technical Implementation
-
-- **LLM Integration**: Uses the NetLogo LLM extension for intelligent agent conversations
-- **Emergent Behavior**: No hardcoded solutions - treasure discovery emerges from agent interactions
-- **Multi-Provider Support**: Works with OpenAI, Claude, Gemini, or Ollama
-- **Safe Navigation**: Robust movement system prevents agents from getting stuck
-- **Visual Storytelling**: Rich graphical feedback system shows the narrative unfolding
-
-## Files
-
-- `hunter-model.nlogox` - Enhanced simulation model (recommended)
-- `new-model.nlogox` - Alternative model version
-- `README.md` - This overview document
-- `USAGE_GUIDE.md` - Complete step-by-step usage instructions
-- `IMPLEMENTATION.md` - Technical implementation details
-- `interface-widgets.md` - Widget configuration reference
-
-## Requirements
-
-- NetLogo 7.0+
-- NetLogo LLM Extension (see main README for build instructions)
-- LLM provider - choose one:
- - **Ollama** (recommended, free, local) - https://ollama.ai
- - **OpenAI** (GPT-4, requires API key)
- - **Anthropic Claude** (requires API key)
- - **Google Gemini** (requires API key)
-
-## Quick Start
-
-1. **Install an LLM provider** (Ollama is easiest):
- ```bash
- # Install Ollama, then:
- ollama pull llama3.2
- ```
-
-2. **Configure the extension**: Edit `demos/config` file with your provider settings
-
-3. **Run the simulation**:
- - Open `hunter-model.nlogox` in NetLogo
- - Click "Setup"
- - Click "Go"
- - Watch the treasure hunt unfold!
-
-4. **Read the guides**:
- - **[USAGE_GUIDE.md](./USAGE_GUIDE.md)** - Complete instructions, troubleshooting, experiments
- - **[IMPLEMENTATION.md](./IMPLEMENTATION.md)** - Technical architecture, code walkthrough
-
-## Educational Value
-
-This demo illustrates key concepts in:
-- **Collective Intelligence**: How groups solve problems no individual can
-- **Emergent Behavior**: Complex outcomes from simple interactions
-- **Knowledge Sharing**: The power of communication and collaboration
-- **AI-Mediated Problem Solving**: Using LLMs to enhance agent reasoning
-- **Spatial Problem Solving**: Navigation and location-based puzzles
diff --git a/demos/emergent-treasure-hunt/USAGE_GUIDE.md b/demos/emergent-treasure-hunt/USAGE_GUIDE.md
deleted file mode 100644
index c7b2446..0000000
--- a/demos/emergent-treasure-hunt/USAGE_GUIDE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-# Treasure Hunt Simulation - Complete Usage Guide
-
-## Quick Start
-
-### Step 1: Install Requirements
-
-1. **NetLogo 7.0+**: Download from https://ccl.northwestern.edu/netlogo/
-2. **LLM Extension**: Build and install (see main README)
-3. **LLM Provider**: Choose one option:
-
- **Option A: Ollama (Recommended for beginners)**
- ```bash
- # Install Ollama from https://ollama.ai
- # Then download a model:
- ollama pull llama3.2
- ```
-
- **Option B: OpenAI**
- - Get API key from https://platform.openai.com
- - Update `demos/config` with your key
-
- **Option C: Claude/Gemini**
- - Get API key from respective providers
- - Update `demos/config` with your key
-
-### Step 2: Configure LLM Provider
-
-Edit `demos/config` file:
-
-```ini
-# For Ollama (FREE, no API key):
-provider=ollama
-model=llama3.2:latest
-
-# For OpenAI (requires API key):
-#provider=openai
-#api_key=sk-your-key-here
-#model=gpt-4o-mini
-```
-
-### Step 3: Run the Simulation
-
-1. Open `hunter-model.nlogox` or `new-model.nlogox` in NetLogo
-2. Click **Setup** button
-3. Click **Go** button
-4. Watch the magic unfold!
-
----
-
-## Understanding the Simulation
-
-### The Story
-
-Five AI agents are trapped in a maze. Each possesses only ONE clue about a hidden treasure:
-
-1. **Agent 0**: "The treasure is golden and round like the sun"
-2. **Agent 1**: "Look where two main paths cross each other"
-3. **Agent 2**: "The special place has coordinates that add up to exactly 15"
-4. **Agent 3**: "It only appears when all clues are combined"
-5. **Agent 4**: "Find the spot furthest from any wall"
-
-**No single agent can find the treasure alone.** They must:
-- Explore the maze using different strategies
-- Meet other agents within communication range
-- Share knowledge through LLM-powered conversations
-- Synthesize insights collaboratively
-- Build collective confidence
-- Discover the treasure location together
-
-### The Four Acts
-
-**Act I: Initialization**
-- Maze is generated using recursive backtracking algorithm
-- 5 agents spawn at random locations
-- Each receives their unique knowledge fragment
-- Exploration strategies are assigned (random, methodical, or wall-follower)
-
-**Act II: Exploration & Communication**
-- Agents wander through maze leaving colored trails
-- When agents meet (within communication range):
- - Golden glow effect spreads
- - LLM facilitates knowledge exchange
- - Both agents synthesize new insights
- - Confidence levels increase
-
-**Act III: Goal Formation**
-- Agents with sufficient learned facts (>1) and confidence (>0.3) analyze their situation
-- LLM helps choose next goal:
- - `explore-more`: Keep searching
- - `find-center`: Move toward maze center
- - `find-crossing`: Seek path intersections
- - `search-systematically`: Check current location
- - `gather-more-info`: Find more agents
-
-**Act IV: Treasure Manifestation**
-- Agent with high confidence (>threshold) at promising location attempts manifestation
-- Collects ALL knowledge from ALL agents
-- LLM synthesizes complete treasure description
-- Treasure appears as pulsating golden orb
-- Celebration effects activate
-
----
-
-## Interface Controls
-
-### Setup Controls
-
-**num-hunters** (slider: 2-10, default: 5)
-- Number of treasure-hunting agents
-- More agents = faster knowledge spread, but more crowded
-
-**communication-range** (slider: 1-5, default: 2)
-- Distance agents can communicate
-- Larger = faster spread, but less realistic
-- Smaller = more challenging, requires more meetings
-
-**confidence-threshold** (slider: 0.5-1.0, default: 0.7)
-- Minimum confidence to attempt treasure manifestation
-- Higher = agents must gather more knowledge
-- Lower = faster discovery, but less certain
-
-**default-strategy** (chooser: random/methodical/wall-follower/mixed)
-- `random`: Agents move randomly through maze
-- `methodical`: Prefer unexplored areas
-- `wall-follower`: Follow walls using right-hand rule
-- `mixed`: Each agent gets random strategy (recommended)
-
-**llm-config-file** (input: string, default: "demos/config")
-- Path to LLM configuration file
-- Can use relative or absolute path
-
-**show-trails?** (switch: on/off)
-- Display colored agent movement trails
-- Beautiful but can clutter visualization
-
-**show-communications?** (switch: on/off)
-- Display golden glow when agents communicate
-- Shows knowledge transfer visually
-
-### Action Buttons
-
-**setup**
-- Generate new maze
-- Create agents with knowledge fragments
-- Reset all variables
-
-**go**
-- Run simulation continuously
-- Agents explore, communicate, discover
-
-**go-once**
-- Step through one tick at a time
-- Useful for debugging
-
-### Monitors
-
-**Treasure Status**
-- "Still searching..." or treasure description when found
-
-**Active Hunters**
-- Number of agents currently in simulation
-
-**Ticks**
-- Time steps elapsed
-
-**Agent Knowledge**
-- Summary of each agent's initial clue
-
-### Plots
-
-**Agent Confidence** (blue line)
-- Shows average confidence over time
-- Should increase as agents communicate
-- Plateaus when knowledge spread saturates
-
-**Knowledge Graph** (black line)
-- Total learned facts accumulated by all agents
-- Exponential growth during active communication phase
-- Indicates knowledge spreading efficiency
-
----
-
-## How It Works (Technical)
-
-### LLM Integration
-
-The simulation uses three types of LLM interactions:
-
-**1. Knowledge Synthesis (llm:chat)**
-```netlogo
-llm:chat (word combined-info
- ". What can we conclude about finding a treasure? Give me new insights.")
-```
-- Agents share their clues
-- LLM synthesizes new understanding
-- Both agents learn the same insight
-
-**2. Goal Selection (llm:choose)**
-```netlogo
-llm:choose situation-summary possible-goals
-```
-- Agent describes current situation
-- LLM picks best goal from predefined options
-- Forces structured decision-making
-
-**3. Treasure Description (llm:chat)**
-```netlogo
-llm:chat (word "Based on all our clues: " combined-knowledge
- ". What exactly is the treasure and what does it look like?")
-```
-- Combines all clues from all agents
-- LLM creates coherent treasure description
-- Poetic synthesis of collective knowledge
-
-### Per-Agent Memory
-
-Each agent maintains separate conversation history:
-- Prevents knowledge leakage between agents
-- Enables unique perspectives
-- LLM builds context over multiple conversations
-- Automatically cleaned up when agents disappear
-
-### Emergent Behavior
-
-No hardcoded solutions! Treasure discovery emerges from:
-- Random maze generation (different each run)
-- Independent agent exploration
-- Organic meeting patterns
-- LLM-synthesized insights
-- Collective confidence building
-
-Same code, different outcomes each time!
-
----
-
-## Troubleshooting
-
-### "Could not load config file"
-
-**Problem**: Config file not found or invalid path
-
-**Solutions**:
-1. Check file exists: `demos/config`
-2. Use absolute path in `llm-config-file` input
-3. Verify file format (key=value pairs)
-
-### "LLM call failed"
-
-**Problem**: Cannot connect to LLM provider
-
-**For Ollama**:
-```bash
-# Check if Ollama is running:
-curl http://localhost:11434/api/tags
-
-# If not, start Ollama and pull model:
-ollama serve
-ollama pull llama3.2
-```
-
-**For Cloud Providers (OpenAI/Claude/Gemini)**:
-1. Verify API key is correct
-2. Check internet connection
-3. Verify API quota/credits available
-4. Increase `timeout_seconds` in config
-
-### Agents Not Communicating
-
-**Problem**: No golden glow effects, no knowledge spread
-
-**Solutions**:
-1. Increase `communication-range` (try 3-4)
-2. Add more agents (`num-hunters` = 7-10)
-3. Enable `show-communications?` to verify
-4. Check console output for LLM errors
-
-### Treasure Never Appears
-
-**Problem**: Agents explore but never manifest treasure
-
-**Solutions**:
-1. Lower `confidence-threshold` (try 0.6)
-2. Increase `communication-range` for more meetings
-3. Wait longer (may take 500-1000 ticks)
-4. Check LLM is responding (watch console output)
-5. Verify LLM timeout is sufficient (increase to 60s)
-
-### Simulation Runs Too Slowly
-
-**Problem**: Each tick takes very long
-
-**Solutions**:
-1. Use faster LLM model (Ollama llama3.2, or GPT-4o-mini)
-2. Reduce `max_tokens` in config (try 200)
-3. Reduce `num-hunters` (try 3-4)
-4. Disable `show-trails?` for less rendering
-5. Consider using `llm:chat-async` for parallel calls
-
-### LLM Responses Are Poor Quality
-
-**Problem**: Agents make illogical decisions, nonsensical insights
-
-**Solutions**:
-1. Use better model (GPT-4o, Claude 3.5 Sonnet, or Gemini 1.5 Pro)
-2. Adjust `temperature` (try 0.5 for more focused responses)
-3. Increase `max_tokens` (try 500-750)
-4. Check prompt engineering in code
-
----
-
-## Experiments to Try
-
-### Experiment 1: Communication Patterns
-- Set `communication-range` to 1 (very close)
-- Set `num-hunters` to 10 (many agents)
-- Watch how long it takes for knowledge to spread
-- Compare to `communication-range` = 5
-
-### Experiment 2: Exploration Strategies
-- Set `default-strategy` to each option individually
-- Measure time to treasure discovery
-- Which strategy is most efficient? Why?
-
-### Experiment 3: Confidence Threshold
-- Run with `confidence-threshold` = 0.5 (low)
-- Run with `confidence-threshold` = 0.9 (high)
-- Does higher threshold lead to better treasure descriptions?
-
-### Experiment 4: LLM Comparison
-- Run same scenario with Ollama llama3.2
-- Run with GPT-4o-mini
-- Run with Claude 3.5 Sonnet
-- Compare quality of knowledge synthesis
-
-### Experiment 5: Agent Population
-- Try with 2 agents (minimal)
-- Try with 10 agents (crowded)
-- What's the optimal number for fastest discovery?
-
-### Experiment 6: Maze Complexity
-- Modify `maze-width` and `maze-height` in code
-- Try 11x11 (small), 21x21 (default), 31x31 (large)
-- How does maze size affect discovery time?
-
----
-
-## Advanced Customization
-
-### Adding New Knowledge Fragments
-
-Edit `assign-knowledge-fragment` in code:
-
-```netlogo
-to-report assign-knowledge-fragment
- let fragments [
- "The treasure is golden and round like the sun"
- "Look where two main paths cross each other"
- "Your new clue here"
- "Another new clue here"
- ]
- let my-index who mod length fragments
- report item my-index fragments
-end
-```
-
-### Customizing LLM Prompts
-
-**Knowledge Synthesis** (line ~426):
-```netlogo
-set conversation-result llm:chat (word
- "You are a treasure hunter sharing clues. " combined-info
- ". What can we conclude? Be concise and insightful.")
-```
-
-**Goal Selection** (line ~466):
-```netlogo
-set current-goal llm:choose (word
- "You are a treasure hunter. " situation-summary
- " What should you do next?") possible-goals
-```
-
-**Treasure Description** (line ~552):
-```netlogo
-let treasure-description llm:chat (word
- "As a mystical narrator, describe the treasure: " combined-knowledge
- ". Paint a vivid picture in 2-3 sentences.")
-```
-
-### Adding Agent Personalities
-
-Add to `treasure-hunters-own`:
-```netlogo
-treasure-hunters-own [
- ...
- personality ; "curious", "cautious", "analytical"
-]
-```
-
-Modify prompts to include personality:
-```netlogo
-llm:chat (word "You are a " personality " treasure hunter. " ...)
-```
-
-### Performance Optimization
-
-Use async for parallel LLM calls:
-```netlogo
-let response llm:chat-async (word combined-info "...")
-; Do other work here
-let result runresult response ; Wait for result when needed
-```
-
----
-
-## Educational Applications
-
-### Computer Science Concepts
-- **Distributed Systems**: Agents with partial knowledge
-- **Emergent Behavior**: Complex outcomes from simple rules
-- **AI Integration**: LLMs as reasoning engines
-- **Multi-Agent Systems**: Communication protocols
-- **Graph Traversal**: Maze navigation algorithms
-
-### Cognitive Science
-- **Collective Intelligence**: Group problem-solving
-- **Knowledge Transfer**: Communication effectiveness
-- **Confidence Building**: Epistemic certainty
-- **Spatial Reasoning**: Location-based puzzles
-
-### Classroom Activities
-1. **Predict outcomes**: Which configuration finds treasure fastest?
-2. **Design clues**: Create new knowledge fragments that work together
-3. **Compare strategies**: Analyze exploration algorithm efficiency
-4. **LLM comparison**: Test different AI models' reasoning
-5. **Modify rules**: What if agents could forget? Or mislead?
-
----
-
-## Credits
-
-This simulation demonstrates:
-- **NetLogo**: Agent-based modeling platform
-- **LLM Extension**: Multi-provider AI integration
-- **Collective Intelligence**: Emergent group problem-solving
-- **Narrative Computation**: Story-driven simulation design
-
-Developed as part of the NetLogo LLM Extension project.
-
-## Further Reading
-
-- [NetLogo Documentation](https://ccl.northwestern.edu/netlogo/docs/)
-- [LLM Extension API Reference](../../docs/API-REFERENCE.md)
-- [Multi-Agent Systems](https://en.wikipedia.org/wiki/Multi-agent_system)
-- [Collective Intelligence](https://en.wikipedia.org/wiki/Collective_intelligence)
-- [Emergent Behavior](https://en.wikipedia.org/wiki/Emergence)
diff --git a/demos/emergent-treasure-hunt/hunter-model.nlogox b/demos/emergent-treasure-hunt/hunter-model.nlogox
deleted file mode 100644
index 23ee916..0000000
--- a/demos/emergent-treasure-hunt/hunter-model.nlogox
+++ /dev/null
@@ -1,1634 +0,0 @@
-
-
- = 0 [
- let west-patch patch (pxcor - 2) pycor
- if west-patch != nobody and [wall?] of west-patch [
- set possible-directions lput west-patch possible-directions
- ]
- ]
-
- if pycor - 2 >= 0 [
- let south-patch patch pxcor (pycor - 2)
- if south-patch != nobody and [wall?] of south-patch [
- set possible-directions lput south-patch possible-directions
- ]
- ]
-
- ; Randomly visit unvisited neighbors
- while [length possible-directions > 0] [
- let next-patch one-of possible-directions
- set possible-directions remove next-patch possible-directions
-
- if [wall?] of next-patch [
- ; Carve path to next cell
- let between-patch patch (([pxcor] of next-patch + pxcor) / 2) (([pycor] of next-patch + pycor) / 2)
- ask between-patch [
- set wall? false
- set pcolor brown + 1
- ]
-
- ; Recursively carve from next cell
- carve-maze-from next-patch
- ]
- ]
- ]
-end
-
-to create-meeting-areas
- ; Create some larger open areas where agents can meet
- let meeting-spots []
- repeat 3 [
- let spot one-of patches with [not wall? and pxcor > 2 and pxcor < maze-width - 3 and pycor > 2 and pycor < maze-height - 3]
- if spot != nobody [
- ask spot [
- ask patches in-radius 1 [
- if wall? [
- set wall? false
- set pcolor brown + 2 ; slightly different color for meeting areas
- ]
- ]
- ]
- set meeting-spots lput spot meeting-spots
- ]
- ]
-end
-
-to add-maze-complexity
- ; Add some additional paths to make the maze more interesting
- repeat 5 [
- let wall-patch one-of patches with [wall? and count neighbors with [not wall?] >= 2]
- if wall-patch != nobody [
- ask wall-patch [
- set wall? false
- set pcolor brown + 1
- ]
- ]
- ]
-end
-
-to setup-hunter
- ; Place hunter at a random open patch
- let open-patches patches with [not wall?]
- if any? open-patches [
- move-to one-of open-patches
- ]
-
- ; Assign unique knowledge fragment
- set knowledge-fragment assign-knowledge-fragment
- set learned-facts []
- set current-goal "explore"
- set confidence-level 0
- set last-communication 0
- set memory-trail []
-
- ; Visual appearance with unique shapes and colors
- set shape one-of ["person" "circle" "triangle" "square" "star"]
- set color one-of [red blue green yellow magenta cyan orange pink]
- set size 0.9
-
- ; Set exploration strategy
- ifelse default-strategy = "mixed" [
- set exploration-strategy one-of ["methodical" "random" "wall-follower"]
- ] [
- set exploration-strategy default-strategy
- ]
-
- ; Enable pen for trail with agent's color (based on switch)
- ifelse show-trails? = true [
- pen-down
- set pen-size 2
- ] [
- pen-up
- ]
-
- ; Log agent creation
- print (word "Hunter " who " created with clue: \"" knowledge-fragment "\"")
- print (word " Strategy: " exploration-strategy ", Starting at (" pxcor ", " pycor ")")
-end
-
-to-report assign-knowledge-fragment
- ; Each agent gets one piece of the treasure puzzle
- let fragments [
- "The treasure is golden and round like the sun"
- "Look where two main paths cross each other"
- "The special place has coordinates that add up to exactly 15"
- "It only appears when all clues are combined"
- "The treasure glows and makes everyone happy"
- "Find the spot furthest from any wall"
- ]
-
- ; Assign unique fragments (cycle through if more agents than fragments)
- let my-index who mod length fragments
- report item my-index fragments
-end
-
-to setup-visual-appearance
- ; Set patch colors and visual effects
- ask patches [
- if not wall? [
- set path-color brown + 1
- ]
- ]
-
- ; Create visual border
- ask patches with [pxcor = 0 or pxcor = maze-width - 1 or pycor = 0 or pycor = maze-height - 1] [
- set pcolor black
- ]
-end
-
-to go
- ; Main simulation loop
- if not any? treasure-hunters [ stop ]
-
- ; Agent actions
- ask treasure-hunters [
- move-through-maze
- detect-nearby-agents
- analyze-current-situation
- take-action-based-on-goal
- update-exploration-memory
- update-agent-appearance
- ]
-
- ; Update environment
- update-visual-effects
- check-treasure-conditions
-
- tick
-
- ; Stop if treasure is found and celebrated
- if treasure-discovered? and any? treasures [
- if ticks mod 30 = 0 [ ; celebration effect every 30 ticks
- celebrate-success
- ]
- ]
-end
-
-to move-through-maze
- ; Different movement strategies
- if exploration-strategy = "random" [
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
-
- if exploration-strategy = "methodical" [
- ; Try to explore unseen areas
- let unexplored patches with [not wall? and not explored? and distance myself <= 1]
- ifelse any? unexplored [
- move-to one-of unexplored
- ] [
- ; If no unexplored nearby, move randomly
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
- ]
-
- if exploration-strategy = "wall-follower" [
- ; Follow walls (right-hand rule) - safe implementation
- right 90
- while [patch-ahead 1 = nobody or [wall?] of patch-ahead 1] [
- right 90
- ]
- ; Only move if destination is valid and not a wall
- let target-patch patch-ahead 1
- if target-patch != nobody and not [wall?] of target-patch [
- move-to target-patch
- ]
- ]
-
- ; Mark current location as explored
- ask patch-here [
- set explored? true
- set pcolor path-color + 0.5 ; slightly brighter for explored areas
- ]
-end
-
-to detect-nearby-agents
- ; Check for other agents within communication range
- let nearby-hunters other treasure-hunters in-radius communication-range
-
- if any? nearby-hunters and (ticks - last-communication) > 5 [
- let communication-partner one-of nearby-hunters
-
- ; Enhanced visual effect for communication
- ask patch-here [
- set meeting-glow 15 ; bright glow effect
- set pcolor yellow
- ]
-
- ; Create spreading communication effect
- ask patches in-radius 1.5 [
- if not wall? [
- set meeting-glow 8
- set pcolor yellow - 1
- ]
- ]
-
- ; Visual connection between communicating agents
- ask communication-partner [
- set color color + 3 ; brighten communicating agent
- pen-up
- move-to patch-here
- pen-down
- move-to [patch-here] of myself
- pen-up
- ]
-
- ; Initiate LLM-based conversation
- communicate-with communication-partner
- set last-communication ticks
- ]
-end
-
-to communicate-with [partner]
- ; Share knowledge using LLM
- let my-info (word knowledge-fragment ". I have learned: " learned-facts)
- let partner-info (word [knowledge-fragment] of partner ". They have learned: " [learned-facts] of partner)
- let combined-info (word "I know: " my-info ". My partner knows: " partner-info)
-
- ; Log the interaction
- print (word "=== AGENT INTERACTION at tick " ticks " ===")
- print (word "Hunter " who " meets Hunter " [who] of partner)
- print (word "Location: (" pxcor ", " pycor ")")
- print "Sharing knowledge..."
-
- ; Use LLM to synthesize information
- let conversation-result ""
- carefully [
- print "Consulting LLM for insights..."
- set conversation-result llm:chat (word combined-info ". What can we conclude about finding a treasure? Give me new insights.")
- print (word "LLM Response: " conversation-result)
- ] [
- ; If LLM call fails, log the error details
- print (word "ERROR: LLM call failed with: " error-message)
- print "Falling back to simple combination"
- set conversation-result (word "Combining clues: " [knowledge-fragment] of partner)
- ]
-
- ; Update learned facts
- if conversation-result != "" [
- set learned-facts lput conversation-result learned-facts
- print (word "Hunter " who " learned: " conversation-result)
-
- ; Partner also learns
- ask partner [
- set learned-facts lput conversation-result learned-facts
- print (word "Hunter " who " also learned this insight")
- ]
- ]
-
- ; Update confidence based on information gained
- set confidence-level confidence-level + 0.2
- if confidence-level > 1 [ set confidence-level 1 ]
- print (word "Confidence levels updated. Hunter " who ": " precision confidence-level 2)
- print "================================"
-end
-
-to analyze-current-situation
- ; Use LLM to determine next goal based on current knowledge
- if length learned-facts > 1 and confidence-level > 0.3 [
- let situation-summary (word "My original clue: " knowledge-fragment
- ". What I've learned from others: " learned-facts
- ". I'm currently at coordinates " pxcor " " pycor
- ". What should be my next goal?")
-
- let possible-goals ["explore-more" "find-center" "find-crossing" "search-systematically" "gather-more-info"]
-
- carefully [
- print (word "Hunter " who " analyzing situation...")
- let old-goal current-goal
- set current-goal llm:choose situation-summary possible-goals
- if current-goal != old-goal [
- print (word "Hunter " who " changed goal from '" old-goal "' to '" current-goal "'")
- ]
- ] [
- ; Fallback if LLM fails
- print (word "ERROR in goal analysis: " error-message)
- set current-goal one-of possible-goals
- print (word "Hunter " who " randomly selected goal: " current-goal)
- ]
- ]
-end
-
-to take-action-based-on-goal
- ; Act based on current goal
- if current-goal = "find-center" [
- ; Move toward center of maze
- let center-patch patch (maze-width / 2) (maze-height / 2)
- if center-patch != nobody [
- face center-patch
- ]
- ]
-
- if current-goal = "find-crossing" [
- ; Look for intersection points
- let crossings patches with [not wall? and count neighbors with [not wall?] >= 3]
- if any? crossings [
- let nearest-crossing min-one-of crossings [distance myself]
- face nearest-crossing
- ]
- ]
-
- if current-goal = "search-systematically" [
- ; Check if current location matches learned criteria
- check-treasure-location
- ]
-end
-
-to check-treasure-location
- ; Check if current location might be treasure location based on accumulated knowledge
- let location-matches? false
-
- ; Analyze learned facts to see if current location fits
- if length learned-facts > 2 [
- let location-description (word "I am at coordinates " pxcor " " pycor
- ". The sum is " (pxcor + pycor)
- ". This location has " count neighbors with [not wall?] " open neighbors."
- ". Based on what I know: " learned-facts
- ". Could this be the treasure location?")
-
- carefully [
- let location-assessment llm:choose location-description ["yes-likely" "no-unlikely" "need-more-info"]
- if location-assessment = "yes-likely" [
- set location-matches? true
- ]
- ] [
- ; Simple fallback check
- if (pxcor + pycor) = 15 and count neighbors with [not wall?] >= 3 [
- set location-matches? true
- ]
- ]
- ]
-
- ; If location seems right and we have enough knowledge, try to manifest treasure
- if location-matches? and confidence-level > confidence-threshold [
- attempt-treasure-manifestation
- ]
-end
-
-to attempt-treasure-manifestation
- ; Try to make treasure appear based on collective knowledge
- if not treasure-discovered? [
- print "=== TREASURE MANIFESTATION ATTEMPT ==="
- print (word "Hunter " who " attempting to manifest treasure at (" pxcor ", " pycor ")")
-
- let all-knowledge []
- ask treasure-hunters [
- set all-knowledge lput knowledge-fragment all-knowledge
- set all-knowledge sentence all-knowledge learned-facts
- ]
-
- let combined-knowledge reduce word all-knowledge
- print "Combining all collective knowledge..."
-
- carefully [
- print "Asking LLM to describe the treasure..."
- let treasure-description llm:chat (word "Based on all our clues: " combined-knowledge
- ". What exactly is the treasure and what does it look like?")
- print (word "LLM treasure description: " treasure-description)
-
- if length treasure-description > 10 [ ; Got a substantial description
- set treasure-definition treasure-description
- set treasure-location patch-here
- print (word "TREASURE MANIFESTED! " treasure-definition)
- manifest-treasure
- ]
- ] [
- ; Fallback treasure manifestation
- print (word "ERROR in treasure description: " error-message)
- print "Checking if we have enough clues for fallback..."
- if length all-knowledge > 4 [ ; Enough clues gathered
- set treasure-definition "A glowing golden orb that brings joy"
- set treasure-location patch-here
- print "TREASURE MANIFESTED using fallback description!"
- manifest-treasure
- ]
- ]
- print "================================"
- ]
-end
-
-to manifest-treasure
- ; Create the treasure at the determined location
- set treasure-discovered? true
-
- ask treasure-location [
- sprout-treasures 1 [
- set shape "circle"
- set color yellow
- set size 1.2
- set glow-phase 0
- set discovered-by nobody
- ]
- set pcolor (yellow + 2) ; golden color
- ]
-
- ; Visual celebration
- ask treasure-hunters [
- set color color + 2 ; brighten colors
- face treasure-location
- ]
-end
-
-to update-exploration-memory
- ; Track where agent has been
- if not member? patch-here memory-trail [
- set memory-trail lput patch-here memory-trail
- ]
-
- ; Keep memory manageable
- if length memory-trail > 50 [
- set memory-trail but-first memory-trail
- ]
-end
-
-to update-agent-appearance
- ; Visual feedback based on confidence level
- let base-color color
-
- ; Size increases with confidence
- set size (0.9 + 0.4 * confidence-level)
-
- ; Brightness increases with confidence
- if confidence-level > 0.5 [
- set color (base-color + 2)
- ]
-
- ; High-confidence agents get special effects
- if confidence-level > 0.8 [
- ; Create halo effect around high-confidence agents
- ask patches in-radius 1 [
- if not wall? and meeting-glow <= 0 [
- set pcolor (pcolor + 0.5)
- ]
- ]
- ]
-end
-
-to update-visual-effects
- ; Update meeting glow effects
- ask patches with [meeting-glow > 0] [
- set meeting-glow meeting-glow - 1
- if meeting-glow <= 0 [
- set pcolor path-color
- if explored? [ set pcolor path-color + 0.5 ]
- ]
- ]
-
- ; Enhanced treasure glow and surrounding effects
- if any? treasures [
- ask treasures [
- set glow-phase glow-phase + 0.3
- ; Pulsing treasure colors
- set color (yellow + 2 + 2 * sin(glow-phase * 180)) ; pulsing golden
- set size (1.2 + 0.3 * sin(glow-phase * 90))
-
- ; Treasure radiates light to surrounding patches
- ask patches in-radius 2 [
- if not wall? [
- let distance-from-treasure distance myself
- let glow-intensity (3 - distance-from-treasure) / 3
- set pcolor (yellow + glow-intensity * 2) ; golden glow
- ]
- ]
-
- ; Sparkle effect
- if random 10 < 3 [
- ask one-of patches in-radius 1.5 with [not wall?] [
- set pcolor white
- set meeting-glow 3
- ]
- ]
- ]
- ]
-end
-
-to check-treasure-conditions
- ; Check if treasure has been found by agents
- if treasure-discovered? and any? treasures [
- let treasure-patch [patch-here] of one-of treasures
- let hunters-at-treasure treasure-hunters-on treasure-patch
-
- if any? hunters-at-treasure [
- ask one-of treasures [
- set discovered-by hunters-at-treasure
- ]
- ]
- ]
-end
-
-to celebrate-success
- ; Visual celebration when treasure is found
- if any? treasures [
- ask one-of treasures [
- ask patches in-radius 3 [
- set pcolor (pcolor + random 3 - 1)
- ]
- ]
-
- ask treasure-hunters [
- right random 60 - 30 ; dance movement
- ]
- ]
-end
-
-; Utility reporters
-to-report knowledge-summary
- ; Report summary of all agent knowledge
- let summary ""
- ask treasure-hunters [
- set summary (word summary "Agent " who ": " knowledge-fragment " | ")
- ]
- report summary
-end
-
-to-report treasure-status
- ; Report current treasure discovery status
- if treasure-discovered? [
- report (word "DISCOVERED: " treasure-definition)
- ]
- report "Still searching..."
-end]]>
-
-
-
-
-
- treasure-status
- ticks
- count treasure-hunters
- knowledge-summary
-
-
-
-
-
-
-
-
-
- set-current-plot "Agent Confidence"
-create-temporary-plot-pen "confidence"
-set-plot-pen-color blue
- if any? treasure-hunters [
- plot mean [confidence-level] of treasure-hunters
-]
-
-
-
-
-
-
-
- if any? treasure-hunters [
- plot sum [length learned-facts] of treasure-hunters
-]
-
-
-
-
-
-
-
-
- demos/config
-
-
- ## WHAT IS IT?
-
-(a general understanding of what the model is trying to show or explain)
-
-## HOW IT WORKS
-
-(what rules the agents use to create the overall behavior of the model)
-
-## HOW TO USE IT
-
-(how to use the model, including a description of each of the items in the Interface tab)
-
-## THINGS TO NOTICE
-
-(suggested things for the user to notice while running the model)
-
-## THINGS TO TRY
-
-(suggested things for the user to try to do (move sliders, switches, etc.) with the model)
-
-## EXTENDING THE MODEL
-
-(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)
-
-## NETLOGO FEATURES
-
-(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)
-
-## RELATED MODELS
-
-(models in the NetLogo Models Library and elsewhere which are of related interest)
-
-## CREDITS AND REFERENCES
-
-(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup repeat 75 [ go ]
-
diff --git a/demos/emergent-treasure-hunt/interface-widgets.md b/demos/emergent-treasure-hunt/interface-widgets.md
deleted file mode 100644
index c6dfe1d..0000000
--- a/demos/emergent-treasure-hunt/interface-widgets.md
+++ /dev/null
@@ -1,396 +0,0 @@
-# NetLogo Interface Widgets Specification
-
-## Emergent Treasure Hunt Model
-
-### Step-by-Step Widget Implementation Guide
-
-## Phase 1: Core Controls (Required)
-
-### 1. Setup Button
-
-**Add Widget โ Button**
-
-- Display text: `setup`
-- Commands: `setup`
-- Forever?: OFF
-- Button type: Observer
-- Action key: S
-- Position: x=10, y=10
-
-### 2. Go Button
-
-**Add Widget โ Button**
-
-- Display text: `go`
-- Commands: `go`
-- Forever?: ON (continuous execution)
-- Button type: Observer
-- Action key: G
-- Position: x=95, y=10
-
-### 3. Go Once Button
-
-**Add Widget โ Button**
-
-- Display text: `go-once`
-- Commands: `go`
-- Forever?: OFF
-- Button type: Observer
-- Position: x=180, y=10
-
-## Phase 2: Essential Monitors
-
-### 4. Treasure Status Monitor
-
-**Add Widget โ Monitor**
-
-- Reporter: `treasure-status`
-- Display name: `Treasure Status`
-- Font size: 11
-- Position: x=10, y=55
-
-### 5. Ticks Monitor
-
-**Add Widget โ Monitor**
-
-- Reporter: `ticks`
-- Display name: `Time Steps`
-- Decimal places: 0
-- Font size: 11
-- Position: x=10, y=100
-
-### 6. Active Hunters Monitor
-
-**Add Widget โ Monitor**
-
-- Reporter: `count treasure-hunters`
-- Display name: `Active Hunters`
-- Decimal places: 0
-- Position: x=120, y=100
-
-### 7. Knowledge Summary Monitor
-
-**Add Widget โ Monitor**
-
-- Reporter: `knowledge-summary`
-- Display name: `Agent Knowledge`
-- Font size: 9
-- Position: x=10, y=145
-- Width: 280
-
-## Phase 3: Configuration Parameters
-
-### 8. Number of Hunters Slider
-
-**Add Widget โ Slider**
-First, add this global variable to your code:
-
-```netlogo
-globals [
- num-hunters ; Add this to existing globals
- ; ... other globals
-]
-```
-
-Then create slider:
-
-- Variable: `num-hunters`
-- Left value: 2
-- Right value: 10
-- Increment: 1
-- Value: 5
-- Display: `Number of Hunters`
-- Position: x=10, y=200
-
-Modify setup procedure:
-
-```netlogo
-to setup
- ; ... existing setup code ...
- create-treasure-hunters num-hunters [ ; Use slider value
- setup-hunter
- ]
- ; ... rest of setup
-end
-```
-
-### 9. Communication Range Slider
-
-Add global:
-
-```netlogo
-globals [
- communication-range ; Add this
- ; ... other globals
-]
-```
-
-Create slider:
-
-- Variable: `communication-range`
-- Left value: 1.0
-- Right value: 5.0
-- Increment: 0.5
-- Value: 2.0
-- Display: `Communication Range`
-- Position: x=10, y=240
-
-Modify detect-nearby-agents:
-
-```netlogo
-to detect-nearby-agents
- let nearby-hunters other treasure-hunters in-radius communication-range
- ; ... rest of procedure
-end
-```
-
-### 10. Confidence Threshold Slider
-
-Add global:
-
-```netlogo
-globals [
- confidence-threshold ; Add this
- ; ... other globals
-]
-```
-
-Create slider:
-
-- Variable: `confidence-threshold`
-- Left value: 0.5
-- Right value: 1.0
-- Increment: 0.1
-- Value: 0.7
-- Display: `Confidence to Manifest`
-- Position: x=10, y=280
-
-Modify check-treasure-location:
-
-```netlogo
-to check-treasure-location
- ; ... existing code ...
- if location-matches? and confidence-level > confidence-threshold [
- attempt-treasure-manifestation
- ]
-end
-```
-
-## Phase 4: Visual Controls
-
-### 11. Show Trails Switch
-
-Add global:
-
-```netlogo
-globals [
- show-trails? ; Add this
- ; ... other globals
-]
-```
-
-**Add Widget โ Switch**
-
-- Variable: `show-trails?`
-- Display: `Show Agent Trails`
-- Position: x=10, y=320
-
-Modify setup-hunter:
-
-```netlogo
-to setup-hunter
- ; ... existing setup ...
- ifelse show-trails? [
- pen-down
- ] [
- pen-up
- ]
- ; ... rest of setup
-end
-```
-
-### 12. Show Communications Switch
-
-Add global:
-
-```netlogo
-globals [
- show-communications? ; Add this
- ; ... other globals
-]
-```
-
-**Add Widget โ Switch**
-
-- Variable: `show-communications?`
-- Display: `Show Communications`
-- Position: x=10, y=350
-
-## Phase 5: Data Visualization
-
-### 13. Agent Confidence Plot
-
-**Add Widget โ Plot**
-
-- Name: `Agent Confidence`
-- X axis label: `Time`
-- Y axis label: `Avg Confidence`
-- X min: 0, X max: 500
-- Y min: 0, Y max: 1.0
-- Position: x=300, y=10
-- Size: width=300, height=150
-
-Plot setup commands:
-
-```netlogo
-set-current-plot "Agent Confidence"
-create-temporary-plot-pen "confidence"
-set-plot-pen-color blue
-```
-
-Plot update commands:
-
-```netlogo
-if any? treasure-hunters [
- plot mean [confidence-level] of treasure-hunters
-]
-```
-
-### 14. Knowledge Accumulation Plot
-
-**Add Widget โ Plot**
-
-- Name: `Knowledge Growth`
-- X axis label: `Time`
-- Y axis label: `Total Facts`
-- X min: 0, X max: 500
-- Position: x=300, y=170
-- Size: width=300, height=150
-
-Plot update commands:
-
-```netlogo
-if any? treasure-hunters [
- plot sum [length learned-facts] of treasure-hunters
-]
-```
-
-## Phase 6: Strategy Selection
-
-### 15. Default Strategy Chooser
-
-Add global:
-
-```netlogo
-globals [
- default-strategy ; Add this
- ; ... other globals
-]
-```
-
-**Add Widget โ Chooser**
-
-- Variable: `default-strategy`
-- Choices: ["random" "methodical" "wall-follower" "mixed"]
-- Display: `Default Strategy`
-- Position: x=10, y=380
-
-Modify setup-hunter:
-
-```netlogo
-to setup-hunter
- ; ... existing setup ...
- ifelse default-strategy = "mixed" [
- set exploration-strategy one-of ["methodical" "random" "wall-follower"]
- ] [
- set exploration-strategy default-strategy
- ]
- ; ... rest of setup
-end
-```
-
-## Phase 7: LLM Configuration
-
-### 16. LLM Config Input
-
-**Add Widget โ Input Box**
-
-- Variable: `llm-config-file`
-- Type: String
-- Default: "config.txt"
-- Display: `LLM Config File`
-- Position: x=10, y=420
-
-Add to globals and setup:
-
-```netlogo
-globals [
- llm-config-file
- ; ... other globals
-]
-
-to setup-llm
- if file-exists? llm-config-file [
- llm:load-config llm-config-file
- ]
-end
-```
-
-### 17. Output Area
-
-**Add Widget โ Output**
-
-- Height: 8 lines
-- Font size: 10
-- Position: x=10, y=460
-- Width: 590
-
-## Implementation Order
-
-1. **Start with Phase 1** - Get basic controls working
-2. **Add Phase 2** - Verify monitors display correctly
-3. **Implement Phase 3** - Test parameter controls
-4. **Add Phase 4** - Enhance visualization
-5. **Implement Phase 5** - Add data plots
-6. **Complete Phase 6-7** - Add advanced features
-
-## Testing Checklist
-
-- [ ] Setup button initializes maze and agents
-- [ ] Go button runs simulation continuously
-- [ ] Monitors update correctly
-- [ ] Sliders affect agent behavior
-- [ ] Plots display data properly
-- [ ] Switches toggle visual features
-- [ ] LLM integration works (if configured)
-
-## Tips for NetLogo Interface Tab
-
-1. **Arrange widgets logically**: Controls at top, parameters on left, plots on right
-2. **Use consistent spacing**: 40-pixel vertical gaps between widget groups
-3. **Group related controls**: Use visual spacing or notes to separate sections
-4. **Set appropriate ranges**: Test min/max values for stability
-5. **Add tooltips**: Right-click widgets โ Edit โ add helpful notes
-6. **Save interface settings**: File โ Save As to preserve layout
-
-## Troubleshooting
-
-**If widgets don't appear:**
-
-- Check variable declarations in globals
-- Verify procedure names match exactly
-- Ensure reporters return appropriate types
-
-**If sliders don't affect behavior:**
-
-- Confirm variables are used in procedures
-- Check that setup reinitializes with new values
-- Verify ranges are appropriate
-
-**If plots don't update:**
-
-- Add plot update code to go procedure
-- Check reporter syntax in plot pens
-- Ensure agents exist before plotting
-
-This completes the widget specification. Follow phases 1-7 in order for smooth implementation.
diff --git a/demos/emergent-treasure-hunt/treasure-hunt-improved.nlogox b/demos/emergent-treasure-hunt/treasure-hunt-improved.nlogox
deleted file mode 100644
index 7016d73..0000000
--- a/demos/emergent-treasure-hunt/treasure-hunt-improved.nlogox
+++ /dev/null
@@ -1,1007 +0,0 @@
-
-
- = 0 [
- let west-patch patch (pxcor - 2) pycor
- if west-patch != nobody and [wall?] of west-patch [
- set possible-directions lput west-patch possible-directions
- ]
- ]
-
- if pycor - 2 >= 0 [
- let south-patch patch pxcor (pycor - 2)
- if south-patch != nobody and [wall?] of south-patch [
- set possible-directions lput south-patch possible-directions
- ]
- ]
-
- ; Visit neighbors randomly
- while [length possible-directions > 0] [
- let next-patch one-of possible-directions
- set possible-directions remove next-patch possible-directions
-
- if [wall?] of next-patch [
- ; Carve between current and next
- let between-patch patch (([pxcor] of next-patch + pxcor) / 2) (([pycor] of next-patch + pycor) / 2)
- ask between-patch [
- set wall? false
- set pcolor brown + 1
- ]
-
- ; Recurse
- carve-maze-from next-patch
- ]
- ]
- ]
-end
-
-to create-meeting-areas
- repeat 3 [
- let spot one-of patches with [not wall? and pxcor > 2 and pxcor < maze-width - 3 and pycor > 2 and pycor < maze-height - 3]
- if spot != nobody [
- ask spot [
- ask patches in-radius 1 [
- if wall? [
- set wall? false
- set pcolor brown + 2
- ]
- ]
- ]
- ]
- ]
-end
-
-to add-maze-complexity
- repeat 5 [
- let wall-patch one-of patches with [wall? and count neighbors with [not wall?] >= 2]
- if wall-patch != nobody [
- ask wall-patch [
- set wall? false
- set pcolor brown + 1
- ]
- ]
- ]
-end
-
-to setup-hunter
- ; Random position
- let open-patches patches with [not wall?]
- if any? open-patches [
- move-to one-of open-patches
- ]
-
- ; Assign clue
- set knowledge-fragment assign-knowledge-fragment
- set learned-facts []
- set current-goal "explore"
- set confidence-level 0
- set last-communication 0
- set memory-trail []
-
- ; Visual
- set shape one-of ["person" "circle" "triangle" "square" "star"]
- set color one-of [red blue green yellow magenta cyan orange pink]
- set size 0.9
-
- ; Strategy
- ifelse default-strategy = "mixed" [
- set exploration-strategy one-of ["methodical" "random" "wall-follower"]
- ] [
- set exploration-strategy default-strategy
- ]
-
- ; Trail
- ifelse show-trails? = true [
- pen-down
- set pen-size 2
- ] [
- pen-up
- ]
-
- print (word "Hunter " who " created with clue: \"" knowledge-fragment "\"")
- print (word " Strategy: " exploration-strategy ", Starting at (" pxcor ", " pycor ")")
-end
-
-to-report assign-knowledge-fragment
- let fragments [
- "The treasure is golden and round like the sun"
- "Look where two main paths cross each other"
- "The special place has coordinates that add up to exactly 15"
- "It only appears when all clues are combined"
- "The treasure glows and makes everyone happy"
- "Find the spot furthest from any wall"
- ]
-
- let my-index who mod length fragments
- report item my-index fragments
-end
-
-to setup-visual-appearance
- ask patches [
- if not wall? [
- set path-color brown + 1
- ]
- ]
-
- ask patches with [pxcor = 0 or pxcor = maze-width - 1 or pycor = 0 or pycor = maze-height - 1] [
- set pcolor black
- ]
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; MAIN LOOP
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to go
- if not any? treasure-hunters [ stop ]
-
- ; Agent actions
- ask treasure-hunters [
- move-through-maze
- detect-nearby-agents
- analyze-current-situation ; FIXED: Now deterministic
- take-action-based-on-goal
- update-exploration-memory
- update-agent-appearance
- ]
-
- ; Periodic knowledge broadcast (every 100 ticks)
- if ticks mod 100 = 0 [
- broadcast-knowledge
- ]
-
- ; Update environment
- update-visual-effects
- check-treasure-conditions
-
- tick
-
- ; Celebration
- if treasure-discovered? and any? treasures [
- if ticks mod 30 = 0 [
- celebrate-success
- ]
- ]
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; MOVEMENT
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to move-through-maze
- if exploration-strategy = "random" [
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
-
- if exploration-strategy = "methodical" [
- let unexplored patches with [not wall? and not explored? and distance myself <= 1]
- ifelse any? unexplored [
- move-to one-of unexplored
- ] [
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
- ]
-
- if exploration-strategy = "wall-follower" [
- right 90
- while [patch-ahead 1 = nobody or [wall?] of patch-ahead 1] [
- right 90
- ]
- let target-patch patch-ahead 1
- if target-patch != nobody and not [wall?] of target-patch [
- move-to target-patch
- ]
- ]
-
- ; Mark explored
- ask patch-here [
- set explored? true
- set pcolor path-color + 0.5
- ]
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; COMMUNICATION (FIXED)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to detect-nearby-agents
- let nearby-hunters other treasure-hunters in-radius communication-range
-
- ; Cooldown of 20 ticks (~2 seconds at 10 FPS) to prevent rate limits
- if any? nearby-hunters and (ticks - last-communication) > 20 [
- let communication-partner one-of nearby-hunters
-
- ; Visual effects
- if show-communications? [
- ask patch-here [
- set meeting-glow 15
- set pcolor yellow
- ]
-
- ask patches in-radius 1.5 [
- if not wall? [
- set meeting-glow 8
- set pcolor yellow - 1
- ]
- ]
- ]
-
- ; Communicate
- communicate-with communication-partner
- set last-communication ticks
- ]
-end
-
-to communicate-with [partner]
- ; FIX #1: COMPLETE KNOWLEDGE SHARING + FIX #2: STRUCTURED PROMPTS + FIX #5: QUALITY CHECK
-
- print (word "=== MEETING at tick " ticks " ===")
- print (word "Hunter " who " โ Hunter " [who] of partner)
- print (word "Location: (" pxcor ", " pycor ")")
-
- ; Build comprehensive context
- let my-clue knowledge-fragment
- let my-learned learned-facts
- let partner-clue [knowledge-fragment] of partner
- let partner-learned [learned-facts] of partner
-
- ; Improved structured prompt
- let synthesis-prompt (word
- "You are analyzing treasure hunt clues. Be SPECIFIC and CONCRETE.\n\n"
- "AGENT 1 KNOWS:\n"
- "- Original clue: \"" my-clue "\"\n"
- "- Learned facts: " my-learned "\n\n"
- "AGENT 2 KNOWS:\n"
- "- Original clue: \"" partner-clue "\"\n"
- "- Learned facts: " partner-learned "\n\n"
- "TASK: Synthesize ONE specific insight about:\n"
- "1. Physical appearance (golden/round/glowing)\n"
- "2. Location criteria (coordinates/intersections/walls)\n\n"
- "FORMAT: 'The treasure [appearance] located at/where [specific location with numbers].'\n\n"
- "GOOD: 'The treasure is a golden sphere located where coordinates sum to 15 at a path intersection.'\n"
- "BAD: 'Work together to find it.'\n\n"
- "Your synthesis:"
- )
-
- let synthesis ""
- carefully [
- print "Consulting LLM..."
- set synthesis llm:chat synthesis-prompt
- print (word "LLM: " synthesis)
- ] [
- print (word "โ LLM failed: " error-message)
- ; Fallback: simple combination
- set synthesis (word "Combined clues suggest: " my-clue " AND " partner-clue)
- ]
-
- ; FIX #5: Validate quality
- let is-useful? false
- if length synthesis >= 20 [
- ; Check for keywords
- if (member? "golden" synthesis or member? "round" synthesis or member? "glowing" synthesis or
- member? "intersection" synthesis or member? "crossing" synthesis or member? "path" synthesis or
- member? "15" synthesis or member? "sum" synthesis or member? "coordinate" synthesis) [
- set is-useful? true
- ]
- ]
-
- ifelse is-useful? [
- ; FIX #1: BOTH agents get EVERYTHING (complete knowledge transfer)
- let combined-facts sentence my-learned partner-learned
- set combined-facts lput synthesis combined-facts
- set combined-facts remove-duplicates combined-facts
-
- ; Both agents now have identical knowledge
- set learned-facts combined-facts
- ask partner [
- set learned-facts combined-facts
- ]
-
- ; Increase confidence
- set confidence-level min list (confidence-level + 0.2) 1
- ask partner [
- set confidence-level min list (confidence-level + 0.2) 1
- ]
-
- print (word "โ Useful knowledge gained!")
- print (word " Confidence: " precision confidence-level 2 " | Knowledge count: " length learned-facts)
- ] [
- ; Poor quality - share facts but don't increase confidence much
- let combined-facts sentence my-learned partner-learned
- set combined-facts remove-duplicates combined-facts
-
- set learned-facts combined-facts
- ask partner [
- set learned-facts combined-facts
- ]
-
- print (word "โ Vague response, minimal confidence gain")
- ]
-
- print "================================"
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; GOAL SYSTEM (FIXED)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to analyze-current-situation
- ; FIX #3: DETERMINISTIC goal progression based on confidence
-
- let old-goal current-goal
-
- if confidence-level < 0.4 [
- set current-goal "explore"
- ]
-
- if confidence-level >= 0.4 and confidence-level < 0.7 [
- set current-goal "find-crossing"
- ]
-
- if confidence-level >= 0.7 [
- set current-goal "search-systematically"
- ]
-
- if old-goal != current-goal [
- print (word "Hunter " who " goal: '" old-goal "' โ '" current-goal "' (confidence: " precision confidence-level 2 ")")
- ]
-end
-
-to take-action-based-on-goal
- if current-goal = "find-center" [
- let center-patch patch (maze-width / 2) (maze-height / 2)
- if center-patch != nobody [
- face center-patch
- ]
- ]
-
- if current-goal = "find-crossing" [
- let crossings patches with [not wall? and count neighbors with [not wall?] >= 3]
- if any? crossings [
- let nearest-crossing min-one-of crossings [distance myself]
- face nearest-crossing
- ]
- ]
-
- if current-goal = "search-systematically" [
- check-treasure-location
- ]
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; LOCATION VALIDATION (FIXED)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to check-treasure-location
- ; FIX #4: Smart validation with better prompts
-
- if length learned-facts < 2 [
- stop ; Need more knowledge
- ]
-
- ; Build detailed location description
- let location-prompt (word
- "CURRENT LOCATION ANALYSIS:\n"
- "- Coordinates: (" pxcor ", " pycor ")\n"
- "- Sum of coordinates: " (pxcor + pycor) "\n"
- "- Open neighbors (paths): " count neighbors with [not wall?] "\n"
- "- Is intersection: " (count neighbors with [not wall?] >= 3) "\n\n"
- "MY KNOWLEDGE ABOUT TREASURE LOCATION:\n"
- learned-facts "\n\n"
- "QUESTION: Based on the knowledge, does THIS location match the treasure criteria?\n"
- "Consider: coordinate sums, intersections, distance from walls.\n\n"
- "Answer ONLY: yes, no, or maybe"
- )
-
- let matches? false
-
- carefully [
- let assessment llm:choose location-prompt ["yes" "no" "maybe"]
-
- if assessment = "yes" [
- set matches? true
- print (word "Hunter " who " at (" pxcor "," pycor "): LLM says 'yes' - attempting manifestation!")
- ]
- ] [
- ; Fallback: check if location looks promising based on knowledge
- let score 0
-
- ; Check if knowledge mentions sum/15/coordinates
- let mentions-sum? false
- foreach learned-facts [ fact ->
- if member? "sum" fact or member? "15" fact or member? "coordinate" fact [
- set mentions-sum? true
- ]
- ]
-
- ; Check if knowledge mentions crossing/intersection
- let mentions-crossing? false
- foreach learned-facts [ fact ->
- if member? "cross" fact or member? "intersection" fact or member? "path" fact [
- set mentions-crossing? true
- ]
- ]
-
- ; Evaluate this location
- if mentions-sum? [
- ; If sum is in knowledge, check if this location's sum is close
- if pxcor + pycor >= 12 and pxcor + pycor <= 18 [
- set score score + 1
- ]
- ]
-
- if mentions-crossing? [
- ; If crossing is in knowledge, check if this is intersection
- if count neighbors with [not wall?] >= 3 [
- set score score + 1
- ]
- ]
-
- if score >= 2 [
- set matches? true
- print (word "Hunter " who " at (" pxcor "," pycor "): Fallback check passes")
- ]
- ]
-
- if matches? and confidence-level >= confidence-threshold [
- attempt-treasure-manifestation
- ]
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; TREASURE MANIFESTATION
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to attempt-treasure-manifestation
- if not treasure-discovered? [
- print "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
- print " TREASURE MANIFESTATION ATTEMPT"
- print "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
- print (word "Hunter " who " at (" pxcor ", " pycor ")")
- print (word "Confidence: " precision confidence-level 2)
-
- ; Collect all knowledge
- let all-knowledge []
- ask treasure-hunters [
- set all-knowledge lput knowledge-fragment all-knowledge
- set all-knowledge sentence all-knowledge learned-facts
- ]
- set all-knowledge remove-duplicates all-knowledge
-
- print (word "Total knowledge pieces: " length all-knowledge)
-
- ; Create treasure description
- let treasure-prompt (word
- "Based on these treasure clues:\n\n"
- all-knowledge "\n\n"
- "Create a vivid, poetic description (2-3 sentences) of what the treasure IS and what it LOOKS like.\n"
- "Include: appearance, glow, location significance.\n\n"
- "Description:"
- )
-
- let description ""
- carefully [
- print "Asking LLM for treasure description..."
- set description llm:chat treasure-prompt
-
- ifelse length description > 10 [
- set treasure-definition description
- set treasure-location patch-here
- manifest-treasure
-
- print "โโโ TREASURE MANIFESTED! โโโ"
- print (word "Description: " description)
- ] [
- print "โ LLM gave short description, retrying..."
- stop
- ]
- ] [
- ; Fallback description
- print (word "โ LLM failed: " error-message)
-
- ifelse length all-knowledge >= 4 [
- set treasure-definition "A radiant golden orb, glowing with ancient light at the intersection of paths."
- set treasure-location patch-here
- manifest-treasure
- print "โ TREASURE MANIFESTED (fallback description)"
- ] [
- print "โ Not enough knowledge for fallback"
- ]
- ]
- print "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
- ]
-end
-
-to manifest-treasure
- set treasure-discovered? true
-
- ask treasure-location [
- sprout-treasures 1 [
- set shape "circle"
- set color yellow
- set size 1.2
- set glow-phase 0
- set discovered-by nobody
- ]
- set pcolor yellow + 2
- ]
-
- ask treasure-hunters [
- set color color + 2
- face treasure-location
- ]
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; BROADCAST (NEW)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to broadcast-knowledge
- ; Every 100 ticks, high-confidence agents share knowledge widely
-
- let broadcasters treasure-hunters with [confidence-level >= 0.5]
-
- if any? broadcasters [
- print (word "--- KNOWLEDGE BROADCAST at tick " ticks " ---")
-
- ask broadcasters [
- let listeners other treasure-hunters in-radius 5 ; Larger radius
-
- if any? listeners [
- ask listeners [
- ; Merge knowledge
- let my-facts learned-facts
- let broadcast-facts [learned-facts] of myself
-
- foreach broadcast-facts [ fact ->
- if not member? fact my-facts [
- set learned-facts lput fact learned-facts
- ]
- ]
-
- ; Small confidence boost
- set confidence-level min list (confidence-level + 0.05) 1
- ]
-
- print (word " Hunter " who " broadcasted to " count listeners " agents")
- ]
- ]
- ]
-end
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; HELPERS
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-to update-exploration-memory
- if not member? patch-here memory-trail [
- set memory-trail lput patch-here memory-trail
- ]
-
- if length memory-trail > 50 [
- set memory-trail but-first memory-trail
- ]
-end
-
-to update-agent-appearance
- ; Size based on confidence
- set size (0.9 + 0.4 * confidence-level)
-
- ; Brightness based on confidence
- if confidence-level > 0.5 [
- let base-color color
- set color (base-color + 2)
- ]
-
- ; Halo for high confidence
- if confidence-level > 0.8 [
- ask patches in-radius 1 [
- if not wall? and meeting-glow <= 0 [
- set pcolor (pcolor + 0.5)
- ]
- ]
- ]
-end
-
-to update-visual-effects
- ; Decay glow
- ask patches with [meeting-glow > 0] [
- set meeting-glow meeting-glow - 1
- if meeting-glow <= 0 [
- set pcolor path-color
- if explored? [ set pcolor path-color + 0.5 ]
- ]
- ]
-
- ; Treasure animation
- if any? treasures [
- ask treasures [
- set glow-phase glow-phase + 0.3
- set color (yellow + 2 + 2 * sin(glow-phase * 180))
- set size (1.2 + 0.3 * sin(glow-phase * 90))
-
- ask patches in-radius 2 [
- if not wall? [
- let distance-from-treasure distance myself
- let glow-intensity (3 - distance-from-treasure) / 3
- set pcolor (yellow + glow-intensity * 2)
- ]
- ]
-
- if random 10 < 3 [
- ask one-of patches in-radius 1.5 with [not wall?] [
- set pcolor white
- set meeting-glow 3
- ]
- ]
- ]
- ]
-end
-
-to check-treasure-conditions
- if treasure-discovered? and any? treasures [
- let treasure-patch [patch-here] of one-of treasures
- let hunters-at-treasure treasure-hunters-on treasure-patch
-
- if any? hunters-at-treasure [
- ask one-of treasures [
- set discovered-by hunters-at-treasure
- ]
- ]
- ]
-end
-
-to celebrate-success
- if any? treasures [
- ask one-of treasures [
- ask patches in-radius 3 [
- set pcolor (pcolor + random 3 - 1)
- ]
- ]
-
- ask treasure-hunters [
- right random 60 - 30
- ]
- ]
-end
-
-to-report knowledge-summary
- let summary ""
- ask treasure-hunters [
- set summary (word summary "A" who ":" (precision confidence-level 2) " ")
- ]
- report summary
-end
-
-to-report treasure-status
- if treasure-discovered? [
- report (word "FOUND: " treasure-definition)
- ]
- report "Searching..."
-end]]>
-
-
-
-
-
- treasure-status
- count treasure-hunters
- ticks
-
-
-
-
-
-
-
-
-
- set-current-plot "Agent Confidence"
-create-temporary-plot-pen "confidence"
-set-plot-pen-color blue
- if any? treasure-hunters [
- plot mean [confidence-level] of treasure-hunters
-]
-
-
-
-
-
-
-
- if any? treasure-hunters [
- plot sum [length learned-facts] of treasure-hunters
-]
-
-
-
-
-
-
-
-
- demos/config
- knowledge-summary
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup repeat 75 [ go ]
-
diff --git a/demos/old-version-files/color-sharing.nlogo b/demos/old-version-files/color-sharing.nlogo
deleted file mode 100644
index a373bff..0000000
--- a/demos/old-version-files/color-sharing.nlogo
+++ /dev/null
@@ -1,593 +0,0 @@
-extensions [ gpt string table]
-
-globals [ colors ]
-
-turtles-own [
- name
- favorite-color
- last-message
- response-reporter
- message
-]
-
-undirected-link-breed [ connections connection ]
-directed-link-breed [ facts fact ]
-
-to setup
- ca
- file-open "apikey"
- gpt:set-api-key file-read-line
- file-close
-
- set-default-shape turtles "person"
- set-default-shape facts "directed"
-
- let names ["Alice" "Ben" "Cindy" "David" "Emily" "Frank"
- "Gina" "Harry" "Isabella" "Jack" "Katie" "Liam"
- "Maggie" "Noah" "Olivia" "Patrick" "Quinn" "Rachel"
- "Samuel" "Tracy" "Ursula" "Vanessa" "William" "Xander"
- "Yvette" "Zack"]
-; let names [ "Gracy" "Myo" "Jasmin" "Wilder" "Osha" "Rik" "Wane" "Ben""Roky" "David" ]
- set colors ["red" "blue" "green"]
- cro num-agents [
-; rt 15
- fd 10
- set size 2
- set name item who names
- set favorite-color one-of colors
- set color runresult favorite-color
- set last-message ""
- ]
- ask turtles [
- create-connections-with min-n-of 2 other turtles [ distance myself ]
-; set response-reporter gpt:chat-async "Generate a list of 10000 first names but do not tell me what it is. Pick a random name from that list. Pick a color. Your response must be a json object with the keys 'name', 'favoriteColor', 'reason', and 'rgbArray'. Make sure your response contains nothing but that json object."
- ]
- ask turtles[
- set label (word name ": " favorite-color)
- gpt:set-history (list
- (list "system" get-prompt)
- )
- ]
- reset-ticks
-end
-
-to go
- ask turtles [
- let messages (sentence [(word name ": " last-message "\n")] of link-neighbors with [ last-message != "" ])
- set response-reporter gpt:chat-async (word
- messages
-; "What do you know about the other agents in the network?"
- " What would you like to say to your neighbors?"
- " Your response must be a raw json object with the keys `message`, `knowledge`, and network."
- " `message` is what you want to say to your neighbors"
- " `knowledge` is an object with agent names as keys and their favorite colors as values or \"unknown\" if you have not yet learned their favorite color."
-; " `network` is an object with agent names as keys and a array of agent names as values indicating which agents are directly connected to which other agents."
- " Your response should not include any formatting."
- )
- ]
- ask facts [ die ]
- ask turtles [
- let raw runresult response-reporter
- carefully [
- let res table:from-json raw
- set message table:get res "message"
- foreach table:to-list table:get res "knowledge" [ pair ->
- create-facts-to other turtles with [ name = first pair ] [
- if member? last pair colors [
- set color runresult last pair
- ]
- ]
- ]
- set label word-wrap (word name ": " message) 30
- set last-message message
- ] [
- show error-message
- show raw
- set message ""
- set last-message message
- ]
- ]
- tick
-end
-
-to-report word-wrap [ str len ]
- let line ""
- let wrapped ""
- foreach (string:split-on " " str) [ w ->
- if length line + length w > len [
- set wrapped (word wrapped "\n" line)
- set line ""
- ]
- set line string:trim (word line " " w)
- ]
- report string:trim (word wrapped "\n" line)
-end
-
-to-report get-prompt
- let p prompt
- let i position "{" p
- let j position "}" p
- while [ is-number? i and is-number? j ] [
- let prefix substring p 0 i
- let suffix substring p (j + 1) (length p)
- let reporter substring p (i + 1) j
-; print "prefix"
-; print prefix
-; print "suffix"
-; print suffix
-; print "reporter"
-; print reporter
- let value runresult reporter
- set p (word prefix value suffix)
- set i position "{" p
- set j position "}" p
- ]
- report p
-; report reduce [ [ p w ] -> (word p " " w) ] (map [ w ->
-; ifelse-value (w string:starts-with? "{" and w string:ends-with? "}") [
-; runresult substring w 1 (length w - 1)
-; ] [
-; w
-; ]
-; ] string:split-on " " prompt)
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-383
-10
-1051
-679
--1
--1
-20.0
-1
-10
-1
-1
-1
-0
-0
-0
-1
--16
-16
--16
-16
-1
-1
-1
-ticks
-30.0
-
-BUTTON
-5
-45
-78
-78
-NIL
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-110
-45
-175
-78
-NIL
-go
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-INPUTBOX
-0
-118
-381
-532
-prompt
-Pretend you are an agent in a social network connected to other agents.\nEvery message you say will be sent to your neighbors and you will receive every message they say.\nYour name is {name} .\nYour favorite color is {favorite-color} .\nYour neighbors are {reduce [[s w] -> (word s \", \" w)] [name] of link-neighbors} .\nYou are trying to figure out the names of your neighbors, the names of those in the network you who are not your neighbors, and the favorite color of all other agents in the network.\nAs you learn about new agents, try to find out their favorite color from your neighbors.\nYour responses must be exactly one short sentence and should clearly state who you are talking to.
-1
-1
-String
-
-SLIDER
-5
-10
-175
-43
-num-agents
-num-agents
-1
-26
-6.0
-1
-1
-NIL
-HORIZONTAL
-
-@#$#@#$#@
-## WHAT IS IT?
-
-(a general understanding of what the model is trying to show or explain)
-
-## HOW IT WORKS
-
-(what rules the agents use to create the overall behavior of the model)
-
-## HOW TO USE IT
-
-(how to use the model, including a description of each of the items in the Interface tab)
-
-## THINGS TO NOTICE
-
-(suggested things for the user to notice while running the model)
-
-## THINGS TO TRY
-
-(suggested things for the user to try to do (move sliders, switches, etc.) with the model)
-
-## EXTENDING THE MODEL
-
-(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)
-
-## NETLOGO FEATURES
-
-(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)
-
-## RELATED MODELS
-
-(models in the NetLogo Models Library and elsewhere which are of related interest)
-
-## CREDITS AND REFERENCES
-
-(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-airplane
-true
-0
-Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15
-
-arrow
-true
-0
-Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150
-
-box
-false
-0
-Polygon -7500403 true true 150 285 285 225 285 75 150 135
-Polygon -7500403 true true 150 135 15 75 150 15 285 75
-Polygon -7500403 true true 15 75 15 225 150 285 150 135
-Line -16777216 false 150 285 150 135
-Line -16777216 false 150 135 15 75
-Line -16777216 false 150 135 285 75
-
-bug
-true
-0
-Circle -7500403 true true 96 182 108
-Circle -7500403 true true 110 127 80
-Circle -7500403 true true 110 75 80
-Line -7500403 true 150 100 80 30
-Line -7500403 true 150 100 220 30
-
-butterfly
-true
-0
-Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
-Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
-Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
-Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
-Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
-Circle -16777216 true false 135 90 30
-Line -16777216 false 150 105 195 60
-Line -16777216 false 150 105 105 60
-
-car
-false
-0
-Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
-Circle -16777216 true false 180 180 90
-Circle -16777216 true false 30 180 90
-Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
-Circle -7500403 true true 47 195 58
-Circle -7500403 true true 195 195 58
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-
-circle 2
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-
-cow
-false
-0
-Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
-Polygon -7500403 true true 73 210 86 251 62 249 48 208
-Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123
-
-cylinder
-false
-0
-Circle -7500403 true true 0 0 300
-
-dot
-false
-0
-Circle -7500403 true true 90 90 120
-
-face happy
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240
-
-face neutral
-false
-0
-Circle -7500403 true true 8 7 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Rectangle -16777216 true false 60 195 240 225
-
-face sad
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183
-
-fish
-false
-0
-Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
-Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
-Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
-Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
-Circle -16777216 true false 215 106 30
-
-flag
-false
-0
-Rectangle -7500403 true true 60 15 75 300
-Polygon -7500403 true true 90 150 270 90 90 30
-Line -7500403 true 75 135 90 135
-Line -7500403 true 75 45 90 45
-
-flower
-false
-0
-Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
-Circle -7500403 true true 85 132 38
-Circle -7500403 true true 130 147 38
-Circle -7500403 true true 192 85 38
-Circle -7500403 true true 85 40 38
-Circle -7500403 true true 177 40 38
-Circle -7500403 true true 177 132 38
-Circle -7500403 true true 70 85 38
-Circle -7500403 true true 130 25 38
-Circle -7500403 true true 96 51 108
-Circle -16777216 true false 113 68 74
-Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
-Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240
-
-house
-false
-0
-Rectangle -7500403 true true 45 120 255 285
-Rectangle -16777216 true false 120 210 180 285
-Polygon -7500403 true true 15 120 150 15 285 120
-Line -16777216 false 30 120 270 120
-
-leaf
-false
-0
-Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
-Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195
-
-line
-true
-0
-Line -7500403 true 150 0 150 300
-
-line half
-true
-0
-Line -7500403 true 150 0 150 150
-
-pentagon
-false
-0
-Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120
-
-person
-false
-0
-Circle -7500403 true true 110 5 80
-Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
-Rectangle -7500403 true true 127 79 172 94
-Polygon -7500403 true true 195 90 240 150 225 180 165 105
-Polygon -7500403 true true 105 90 60 150 75 180 135 105
-
-plant
-false
-0
-Rectangle -7500403 true true 135 90 165 300
-Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
-Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
-Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
-Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
-Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
-Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
-Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90
-
-sheep
-false
-15
-Circle -1 true true 203 65 88
-Circle -1 true true 70 65 162
-Circle -1 true true 150 105 120
-Polygon -7500403 true false 218 120 240 165 255 165 278 120
-Circle -7500403 true false 214 72 67
-Rectangle -1 true true 164 223 179 298
-Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
-Circle -1 true true 3 83 150
-Rectangle -1 true true 65 221 80 296
-Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
-Polygon -7500403 true false 276 85 285 105 302 99 294 83
-Polygon -7500403 true false 219 85 210 105 193 99 201 83
-
-square
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-
-square 2
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-Rectangle -16777216 true false 60 60 240 240
-
-star
-false
-0
-Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108
-
-target
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-Circle -7500403 true true 60 60 180
-Circle -16777216 true false 90 90 120
-Circle -7500403 true true 120 120 60
-
-tree
-false
-0
-Circle -7500403 true true 118 3 94
-Rectangle -6459832 true false 120 195 180 300
-Circle -7500403 true true 65 21 108
-Circle -7500403 true true 116 41 127
-Circle -7500403 true true 45 90 120
-Circle -7500403 true true 104 74 152
-
-triangle
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-
-triangle 2
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-Polygon -16777216 true false 151 99 225 223 75 224
-
-truck
-false
-0
-Rectangle -7500403 true true 4 45 195 187
-Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
-Rectangle -1 true false 195 60 195 105
-Polygon -16777216 true false 238 112 252 141 219 141 218 112
-Circle -16777216 true false 234 174 42
-Rectangle -7500403 true true 181 185 214 194
-Circle -16777216 true false 144 174 42
-Circle -16777216 true false 24 174 42
-Circle -7500403 false true 24 174 42
-Circle -7500403 false true 144 174 42
-Circle -7500403 false true 234 174 42
-
-turtle
-true
-0
-Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
-Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
-Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
-Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
-Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
-Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99
-
-wheel
-false
-0
-Circle -7500403 true true 3 3 294
-Circle -16777216 true false 30 30 240
-Line -7500403 true 150 285 150 15
-Line -7500403 true 15 150 285 150
-Circle -7500403 true true 120 120 60
-Line -7500403 true 216 40 79 269
-Line -7500403 true 40 84 269 221
-Line -7500403 true 40 216 269 79
-Line -7500403 true 84 40 221 269
-
-wolf
-false
-0
-Polygon -16777216 true false 253 133 245 131 245 133
-Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
-Polygon -7500403 true true -1 195 14 180 36 166 40 153 53 140 82 131 134 133 159 126 188 115 227 108 236 102 238 98 268 86 269 92 281 87 269 103 269 113
-
-x
-false
-0
-Polygon -7500403 true true 270 75 225 30 30 225 75 270
-Polygon -7500403 true true 30 75 75 30 270 225 225 270
-@#$#@#$#@
-NetLogo 6.3.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-
-directed
-2.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/emergent-treasure-hunt.nlogo b/demos/old-version-files/emergent-treasure-hunt.nlogo
deleted file mode 100644
index a01da26..0000000
--- a/demos/old-version-files/emergent-treasure-hunt.nlogo
+++ /dev/null
@@ -1,715 +0,0 @@
-; ABOUTME: Emergent treasure hunt where agents discover what treasure is and where to find it through LLM-mediated communication in a maze
-; ABOUTME: Agents share partial knowledge clues and use collaborative reasoning to solve the mystery
-
-extensions [ llm ]
-
-breed [treasure-hunters hunter]
-breed [treasures treasure]
-
-globals [
- maze-width
- maze-height
- treasure-discovered?
- treasure-definition
- treasure-location
- communication-pairs
- ; Interface widget variables
- ; num-hunters ; Number of treasure hunters (slider)
- ;communication-range ; Range for agent communication (slider)
- ; confidence-threshold ; Confidence level needed to manifest treasure (slider)
- ; show-trails? ; Whether to show agent trails (switch)
- ; show-communications? ; Whether to show communication visuals (switch)
- ; default-strategy ; Default exploration strategy (chooser)
- ; llm-config-file ; Path to LLM configuration file (input)
-
-]
-
-patches-own [
- wall? ; true if this patch is a wall
- explored? ; true if an agent has been here
- meeting-glow ; visual effect when agents meet here
- path-color ; color for path visualization
-]
-
-treasure-hunters-own [
- knowledge-fragment ; the one clue each agent knows
- learned-facts ; accumulated knowledge from conversations
- current-goal ; what agent is trying to do now
- confidence-level ; how confident agent is in their understanding
- last-communication ; tick when last communicated
- exploration-strategy ; how this agent moves through maze
- memory-trail ; patches this agent has visited
-]
-
-treasures-own [
- glow-phase ; for animation effect
- discovered-by ; which agents found it
-]
-
-to setup
- clear-all
-
- ; Initialize interface variables with defaults if not set
- if num-hunters = 0 [ set num-hunters 5 ]
- if communication-range = 0 [ set communication-range 2 ]
- if confidence-threshold = 0 [ set confidence-threshold 0.7 ]
- if default-strategy = 0 [ set default-strategy "mixed" ]
- ; For config file, try to use the one in the same directory as the model
- if llm-config-file = 0 [
- ; Try just the filename first (works if model saved and opened from same location)
- set llm-config-file "demos/config"
- ]
- ; Initialize boolean switches (0 means not set by interface)
- if show-trails? = 0 [ set show-trails? true ]
- if show-communications? = 0 [ set show-communications? true ]
-
- ; Initialize LLM extension with default configuration
- setup-llm
-
- ; Set world dimensions for good maze
- set maze-width 21 ; odd number for proper maze generation
- set maze-height 21
- resize-world 0 (maze-width - 1) 0 (maze-height - 1)
-
- ; Initialize global variables
- set treasure-discovered? false
- set treasure-definition ""
- set treasure-location nobody
- set communication-pairs []
-
- ; Generate the maze
- generate-maze
-
- ; Create treasure-hunting agents with unique knowledge
- create-treasure-hunters num-hunters [
- setup-hunter
- ]
-
- ; Visual setup
- setup-visual-appearance
-
- reset-ticks
-end
-
-to setup-llm
- ; Load LLM configuration from file if it exists
- if llm-config-file != 0 and llm-config-file != "" [
- ; Try loading the config file
- ; Note: The file should be in the same directory as the model
- ; or you can use an absolute path
- carefully [
- llm:load-config llm-config-file
- ] [
- ; If loading fails, use Ollama as default
- print (word "Note: Could not load " llm-config-file ". Using Ollama with llama3.2")
- llm:set-provider "ollama"
- llm:set-model "llama3.2"
- ]
- ]
-end
-
-to generate-maze
- ; Initialize all patches as walls
- ask patches [
- set wall? true
- set explored? false
- set meeting-glow 0
- set path-color gray - 2
- set pcolor gray - 2 ; dark gray walls
- ]
-
- ; Create a simple maze using recursive backtracking algorithm
- ; Start with a grid of walls and carve out passages
- let start-patch patch 1 1
- ask start-patch [
- set wall? false
- set pcolor brown + 1 ; light tan path
- ]
-
- ; Carve maze paths
- carve-maze-from start-patch
-
- ; Ensure there are some open meeting areas
- create-meeting-areas
-
- ; Create dead ends and complexity
- add-maze-complexity
-end
-
-to carve-maze-from [current-patch]
- ; Recursive backtracking maze generation
- ask current-patch [
- set wall? false
- set pcolor brown + 1
-
- ; Get possible directions (2 patches away to maintain walls)
- let possible-directions []
-
- ; Check each cardinal direction
- if pxcor + 2 < maze-width [
- let east-patch patch (pxcor + 2) pycor
- if east-patch != nobody and [wall?] of east-patch [
- set possible-directions lput east-patch possible-directions
- ]
- ]
-
- if pycor + 2 < maze-height [
- let north-patch patch pxcor (pycor + 2)
- if north-patch != nobody and [wall?] of north-patch [
- set possible-directions lput north-patch possible-directions
- ]
- ]
-
- if pxcor - 2 >= 0 [
- let west-patch patch (pxcor - 2) pycor
- if west-patch != nobody and [wall?] of west-patch [
- set possible-directions lput west-patch possible-directions
- ]
- ]
-
- if pycor - 2 >= 0 [
- let south-patch patch pxcor (pycor - 2)
- if south-patch != nobody and [wall?] of south-patch [
- set possible-directions lput south-patch possible-directions
- ]
- ]
-
- ; Randomly visit unvisited neighbors
- while [length possible-directions > 0] [
- let next-patch one-of possible-directions
- set possible-directions remove next-patch possible-directions
-
- if [wall?] of next-patch [
- ; Carve path to next cell
- let between-patch patch (([pxcor] of next-patch + pxcor) / 2) (([pycor] of next-patch + pycor) / 2)
- ask between-patch [
- set wall? false
- set pcolor brown + 1
- ]
-
- ; Recursively carve from next cell
- carve-maze-from next-patch
- ]
- ]
- ]
-end
-
-to create-meeting-areas
- ; Create some larger open areas where agents can meet
- let meeting-spots []
- repeat 3 [
- let spot one-of patches with [not wall? and pxcor > 2 and pxcor < maze-width - 3 and pycor > 2 and pycor < maze-height - 3]
- if spot != nobody [
- ask spot [
- ask patches in-radius 1 [
- if wall? [
- set wall? false
- set pcolor brown + 2 ; slightly different color for meeting areas
- ]
- ]
- ]
- set meeting-spots lput spot meeting-spots
- ]
- ]
-end
-
-to add-maze-complexity
- ; Add some additional paths to make the maze more interesting
- repeat 5 [
- let wall-patch one-of patches with [wall? and count neighbors with [not wall?] >= 2]
- if wall-patch != nobody [
- ask wall-patch [
- set wall? false
- set pcolor brown + 1
- ]
- ]
- ]
-end
-
-to setup-hunter
- ; Place hunter at a random open patch
- let open-patches patches with [not wall?]
- if any? open-patches [
- move-to one-of open-patches
- ]
-
- ; Assign unique knowledge fragment
- set knowledge-fragment assign-knowledge-fragment
- set learned-facts []
- set current-goal "explore"
- set confidence-level 0
- set last-communication 0
- set memory-trail []
-
- ; Visual appearance with unique shapes and colors
- set shape one-of ["person" "circle" "triangle" "square" "star"]
- set color one-of [red blue green yellow magenta cyan orange pink]
- set size 0.9
-
- ; Set exploration strategy
- ifelse default-strategy = "mixed" [
- set exploration-strategy one-of ["methodical" "random" "wall-follower"]
- ] [
- set exploration-strategy default-strategy
- ]
-
- ; Enable pen for trail with agent's color (based on switch)
- ifelse show-trails? = true [
- pen-down
- set pen-size 2
- ] [
- pen-up
- ]
-
- ; Log agent creation
- print (word "Hunter " who " created with clue: \"" knowledge-fragment "\"")
- print (word " Strategy: " exploration-strategy ", Starting at (" pxcor ", " pycor ")")
-end
-
-to-report assign-knowledge-fragment
- ; Each agent gets one piece of the treasure puzzle
- let fragments [
- "The treasure is golden and round like the sun"
- "Look where two main paths cross each other"
- "The special place has coordinates that add up to exactly 15"
- "It only appears when all clues are combined"
- "The treasure glows and makes everyone happy"
- "Find the spot furthest from any wall"
- ]
-
- ; Assign unique fragments (cycle through if more agents than fragments)
- let my-index who mod length fragments
- report item my-index fragments
-end
-
-to setup-visual-appearance
- ; Set patch colors and visual effects
- ask patches [
- if not wall? [
- set path-color brown + 1
- ]
- ]
-
- ; Create visual border
- ask patches with [pxcor = 0 or pxcor = maze-width - 1 or pycor = 0 or pycor = maze-height - 1] [
- set pcolor black
- ]
-end
-
-to go
- ; Main simulation loop
- if not any? treasure-hunters [ stop ]
-
- ; Agent actions
- ask treasure-hunters [
- move-through-maze
- detect-nearby-agents
- analyze-current-situation
- take-action-based-on-goal
- update-exploration-memory
- update-agent-appearance
- ]
-
- ; Update environment
- update-visual-effects
- check-treasure-conditions
-
- tick
-
- ; Stop if treasure is found and celebrated
- if treasure-discovered? and any? treasures [
- if ticks mod 30 = 0 [ ; celebration effect every 30 ticks
- celebrate-success
- ]
- ]
-end
-
-to move-through-maze
- ; Different movement strategies
- if exploration-strategy = "random" [
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
-
- if exploration-strategy = "methodical" [
- ; Try to explore unseen areas
- let unexplored patches with [not wall? and not explored? and distance myself <= 1]
- ifelse any? unexplored [
- move-to one-of unexplored
- ] [
- ; If no unexplored nearby, move randomly
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
- ]
-
- if exploration-strategy = "wall-follower" [
- ; Follow walls (right-hand rule) - safe implementation
- right 90
- while [patch-ahead 1 = nobody or [wall?] of patch-ahead 1] [
- right 90
- ]
- ; Only move if destination is valid and not a wall
- let target-patch patch-ahead 1
- if target-patch != nobody and not [wall?] of target-patch [
- move-to target-patch
- ]
- ]
-
- ; Mark current location as explored
- ask patch-here [
- set explored? true
- set pcolor path-color + 0.5 ; slightly brighter for explored areas
- ]
-end
-
-to detect-nearby-agents
- ; Check for other agents within communication range
- let nearby-hunters other treasure-hunters in-radius communication-range
-
- if any? nearby-hunters and (ticks - last-communication) > 5 [
- let communication-partner one-of nearby-hunters
-
- ; Enhanced visual effect for communication
- ask patch-here [
- set meeting-glow 15 ; bright glow effect
- set pcolor yellow
- ]
-
- ; Create spreading communication effect
- ask patches in-radius 1.5 [
- if not wall? [
- set meeting-glow 8
- set pcolor yellow - 1
- ]
- ]
-
- ; Visual connection between communicating agents
- ask communication-partner [
- set color color + 3 ; brighten communicating agent
- pen-up
- move-to patch-here
- pen-down
- move-to [patch-here] of myself
- pen-up
- ]
-
- ; Initiate LLM-based conversation
- communicate-with communication-partner
- set last-communication ticks
- ]
-end
-
-to communicate-with [partner]
- ; Share knowledge using LLM
- let my-info (word knowledge-fragment ". I have learned: " learned-facts)
- let partner-info (word [knowledge-fragment] of partner ". They have learned: " [learned-facts] of partner)
- let combined-info (word "I know: " my-info ". My partner knows: " partner-info)
-
- ; Log the interaction
- print (word "=== AGENT INTERACTION at tick " ticks " ===")
- print (word "Hunter " who " meets Hunter " [who] of partner)
- print (word "Location: (" pxcor ", " pycor ")")
- print "Sharing knowledge..."
-
- ; Use LLM to synthesize information
- let conversation-result ""
- carefully [
- print "Consulting LLM for insights..."
- set conversation-result llm:chat (word combined-info ". What can we conclude about finding a treasure? Give me new insights.")
- print (word "LLM Response: " conversation-result)
- ] [
- ; If LLM call fails, log the error details
- print (word "ERROR: LLM call failed with: " error-message)
- print "Falling back to simple combination"
- set conversation-result (word "Combining clues: " [knowledge-fragment] of partner)
- ]
-
- ; Update learned facts
- if conversation-result != "" [
- set learned-facts lput conversation-result learned-facts
- print (word "Hunter " who " learned: " conversation-result)
-
- ; Partner also learns
- ask partner [
- set learned-facts lput conversation-result learned-facts
- print (word "Hunter " who " also learned this insight")
- ]
- ]
-
- ; Update confidence based on information gained
- set confidence-level confidence-level + 0.2
- if confidence-level > 1 [ set confidence-level 1 ]
- print (word "Confidence levels updated. Hunter " who ": " precision confidence-level 2)
- print "================================"
-end
-
-to analyze-current-situation
- ; Use LLM to determine next goal based on current knowledge
- if length learned-facts > 1 and confidence-level > 0.3 [
- let situation-summary (word "My original clue: " knowledge-fragment
- ". What I've learned from others: " learned-facts
- ". I'm currently at coordinates " pxcor " " pycor
- ". What should be my next goal?")
-
- let possible-goals ["explore-more" "find-center" "find-crossing" "search-systematically" "gather-more-info"]
-
- carefully [
- print (word "Hunter " who " analyzing situation...")
- let old-goal current-goal
- set current-goal llm:choose situation-summary possible-goals
- if current-goal != old-goal [
- print (word "Hunter " who " changed goal from '" old-goal "' to '" current-goal "'")
- ]
- ] [
- ; Fallback if LLM fails
- print (word "ERROR in goal analysis: " error-message)
- set current-goal one-of possible-goals
- print (word "Hunter " who " randomly selected goal: " current-goal)
- ]
- ]
-end
-
-to take-action-based-on-goal
- ; Act based on current goal
- if current-goal = "find-center" [
- ; Move toward center of maze
- let center-patch patch (maze-width / 2) (maze-height / 2)
- if center-patch != nobody [
- face center-patch
- ]
- ]
-
- if current-goal = "find-crossing" [
- ; Look for intersection points
- let crossings patches with [not wall? and count neighbors with [not wall?] >= 3]
- if any? crossings [
- let nearest-crossing min-one-of crossings [distance myself]
- face nearest-crossing
- ]
- ]
-
- if current-goal = "search-systematically" [
- ; Check if current location matches learned criteria
- check-treasure-location
- ]
-end
-
-to check-treasure-location
- ; Check if current location might be treasure location based on accumulated knowledge
- let location-matches? false
-
- ; Analyze learned facts to see if current location fits
- if length learned-facts > 2 [
- let location-description (word "I am at coordinates " pxcor " " pycor
- ". The sum is " (pxcor + pycor)
- ". This location has " count neighbors with [not wall?] " open neighbors."
- ". Based on what I know: " learned-facts
- ". Could this be the treasure location?")
-
- carefully [
- let location-assessment llm:choose location-description ["yes-likely" "no-unlikely" "need-more-info"]
- if location-assessment = "yes-likely" [
- set location-matches? true
- ]
- ] [
- ; Simple fallback check
- if (pxcor + pycor) = 15 and count neighbors with [not wall?] >= 3 [
- set location-matches? true
- ]
- ]
- ]
-
- ; If location seems right and we have enough knowledge, try to manifest treasure
- if location-matches? and confidence-level > confidence-threshold [
- attempt-treasure-manifestation
- ]
-end
-
-to attempt-treasure-manifestation
- ; Try to make treasure appear based on collective knowledge
- if not treasure-discovered? [
- print "=== TREASURE MANIFESTATION ATTEMPT ==="
- print (word "Hunter " who " attempting to manifest treasure at (" pxcor ", " pycor ")")
-
- let all-knowledge []
- ask treasure-hunters [
- set all-knowledge lput knowledge-fragment all-knowledge
- set all-knowledge sentence all-knowledge learned-facts
- ]
-
- let combined-knowledge reduce word all-knowledge
- print "Combining all collective knowledge..."
-
- carefully [
- print "Asking LLM to describe the treasure..."
- let treasure-description llm:chat (word "Based on all our clues: " combined-knowledge
- ". What exactly is the treasure and what does it look like?")
- print (word "LLM treasure description: " treasure-description)
-
- if length treasure-description > 10 [ ; Got a substantial description
- set treasure-definition treasure-description
- set treasure-location patch-here
- print (word "TREASURE MANIFESTED! " treasure-definition)
- manifest-treasure
- ]
- ] [
- ; Fallback treasure manifestation
- print (word "ERROR in treasure description: " error-message)
- print "Checking if we have enough clues for fallback..."
- if length all-knowledge > 4 [ ; Enough clues gathered
- set treasure-definition "A glowing golden orb that brings joy"
- set treasure-location patch-here
- print "TREASURE MANIFESTED using fallback description!"
- manifest-treasure
- ]
- ]
- print "================================"
- ]
-end
-
-to manifest-treasure
- ; Create the treasure at the determined location
- set treasure-discovered? true
-
- ask treasure-location [
- sprout-treasures 1 [
- set shape "circle"
- set color yellow
- set size 1.2
- set glow-phase 0
- set discovered-by nobody
- ]
- set pcolor (yellow + 2) ; golden color
- ]
-
- ; Visual celebration
- ask treasure-hunters [
- set color color + 2 ; brighten colors
- face treasure-location
- ]
-end
-
-to update-exploration-memory
- ; Track where agent has been
- if not member? patch-here memory-trail [
- set memory-trail lput patch-here memory-trail
- ]
-
- ; Keep memory manageable
- if length memory-trail > 50 [
- set memory-trail but-first memory-trail
- ]
-end
-
-to update-agent-appearance
- ; Visual feedback based on confidence level
- let base-color color
-
- ; Size increases with confidence
- set size (0.9 + 0.4 * confidence-level)
-
- ; Brightness increases with confidence
- if confidence-level > 0.5 [
- set color (base-color + 2)
- ]
-
- ; High-confidence agents get special effects
- if confidence-level > 0.8 [
- ; Create halo effect around high-confidence agents
- ask patches in-radius 1 [
- if not wall? and meeting-glow <= 0 [
- set pcolor (pcolor + 0.5)
- ]
- ]
- ]
-end
-
-to update-visual-effects
- ; Update meeting glow effects
- ask patches with [meeting-glow > 0] [
- set meeting-glow meeting-glow - 1
- if meeting-glow <= 0 [
- set pcolor path-color
- if explored? [ set pcolor path-color + 0.5 ]
- ]
- ]
-
- ; Enhanced treasure glow and surrounding effects
- if any? treasures [
- ask treasures [
- set glow-phase glow-phase + 0.3
- ; Pulsing treasure colors
- set color (yellow + 2 + 2 * sin(glow-phase * 180)) ; pulsing golden
- set size (1.2 + 0.3 * sin(glow-phase * 90))
-
- ; Treasure radiates light to surrounding patches
- ask patches in-radius 2 [
- if not wall? [
- let distance-from-treasure distance myself
- let glow-intensity (3 - distance-from-treasure) / 3
- set pcolor (yellow + glow-intensity * 2) ; golden glow
- ]
- ]
-
- ; Sparkle effect
- if random 10 < 3 [
- ask one-of patches in-radius 1.5 with [not wall?] [
- set pcolor white
- set meeting-glow 3
- ]
- ]
- ]
- ]
-end
-
-to check-treasure-conditions
- ; Check if treasure has been found by agents
- if treasure-discovered? and any? treasures [
- let treasure-patch [patch-here] of one-of treasures
- let hunters-at-treasure treasure-hunters-on treasure-patch
-
- if any? hunters-at-treasure [
- ask one-of treasures [
- set discovered-by hunters-at-treasure
- ]
- ]
- ]
-end
-
-to celebrate-success
- ; Visual celebration when treasure is found
- if any? treasures [
- ask one-of treasures [
- ask patches in-radius 3 [
- set pcolor (pcolor + random 3 - 1)
- ]
- ]
-
- ask treasure-hunters [
- right random 60 - 30 ; dance movement
- ]
- ]
-end
-
-; Utility reporters
-to-report knowledge-summary
- ; Report summary of all agent knowledge
- let summary ""
- ask treasure-hunters [
- set summary (word summary "Agent " who ": " knowledge-fragment " | ")
- ]
- report summary
-end
-
-to-report treasure-status
- ; Report current treasure discovery status
- if treasure-discovered? [
- report (word "DISCOVERED: " treasure-definition)
- ]
- report "Still searching..."
-end
diff --git a/demos/old-version-files/llm-code-evolution-env.nlogox b/demos/old-version-files/llm-code-evolution-env.nlogox
deleted file mode 100644
index 90888d7..0000000
--- a/demos/old-version-files/llm-code-evolution-env.nlogox
+++ /dev/null
@@ -1,1220 +0,0 @@
-extensions [ llm table fp rnd ]
-
-globals [
- generation
- init-rule
- generation-stats
- best-rule
- best-rule-fitness
- error-log
- init-pseudocode
- evolution-history
-]
-
-breed [llm-agents llm-agent]
-breed [food-sources food-source]
-
-llm-agents-own [
- input
- rule
- energy
- lifetime
- food-collected
- parent-id
- parent-rule
- pseudocode
- parent-pseudocode
-]
-
-;;; Setup Procedures
-
-to setup-params
- if use-config-file? [
- carefully [
- run word "setup-params-" config-file
- ] [
- user-message word config-file " is not a valid config file."
- ]
- ]
-end
-
-to-report get-additional-params
- report (list
- list "num-food-sources" num-food-sources
- list "init-rule" init-rule
- list "init-pseudocode" init-pseudocode
- )
-end
-
-to setup-llm-agents
- create-llm-agents num-llm-agents [
- set color red
- setxy random-xcor random-ycor
- set rule init-rule
- set parent-id "na"
- set parent-rule "na"
- set pseudocode init-pseudocode
- set parent-pseudocode "na"
- init-agent-params
- ]
-end
-
-to init-agent-params
- set energy 0
- set food-collected 0
- set lifetime 0
-end
-
-to spawn-food [num]
- create-food-sources num [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
-end
-
-to setup
- clear-all
-
- ; Initialize LLM extension
- llm:load-config llm-config-file
- llm:set-provider llm-provider
- if llm-provider != "ollama" [
- llm:set-api-key llm-api-key
- ]
- llm:set-model llm-model
-
- set init-rule "lt random 20 rt random 20 fd 1"
- set init-pseudocode "Take left turn randomly within 0-20 degrees, then take right turn randomly within 0-20 degrees and move forward 1"
-
- set generation 0
- set generation-stats []
- set error-log []
- set best-rule-fitness 0
- set evolution-history []
-
- spawn-food num-food-sources
- setup-llm-agents
- setup-params
- if logging? [ setup-logger get-additional-params ]
- reset-ticks
-end
-
-;;; Go Procedures
-
-to go
- do-plotting
- ask llm-agents [
- set lifetime lifetime + 1
- set input get-observation
- run-rule
- eat-food
- ]
- evolve-agents
- replenish-food
- tick
-end
-
-to run-rule
- carefully [
- run rule
- ] [
- let error-info (word
- "ERROR WHILE RUNNING RULE: " rule
- " | Agent: " who
- " | Tick: " ticks
- " | Fitness: " fitness
- " | Lifetime: " lifetime
- " | Food Collected: " food-collected
- " | Input: " input
- " | Error: " error-message
- )
- if ticks mod ticks-per-generation = 1 [
- if verbose? [ print error-info ]
- set error-log lput error-info error-log
- ]
- ]
-end
-
-to evolve-agents
- if ticks >= 1 and ticks mod ticks-per-generation = 0 [
- set generation generation + 1
- print word "\nGeneration: " generation
-
- let parents select-agents
- let kill-num length parents
-
- let kill-dict agent-dict min-n-of kill-num llm-agents [fitness]
- let best-dict agent-dict turtle-set parents
- let new-agent-ids []
-
- foreach parents [ parent ->
- ask parent [
- let my-parent-id who
- let my-rule rule
- let my-pseudocode pseudocode
- hatch 1 [
- set parent-id my-parent-id
- set parent-rule my-rule
- set parent-pseudocode my-pseudocode
- set rule mutate-rule-with-llm my-rule
- init-agent-params
- set new-agent-ids lput who new-agent-ids
- ]
- ]
- ]
-
- ask min-n-of kill-num llm-agents with [not member? who new-agent-ids] [fitness] [ die ]
-
- let new-dict agent-dict llm-agents with [member? who new-agent-ids]
- update-generation-stats
- log-metrics (list best-dict new-dict kill-dict)
- set error-log []
-
- ask llm-agents [
- set food-collected 0
- set energy 0
- ]
- ]
-end
-
-to-report mutate-rule-with-llm [current-rule]
- let mutation-prompt (word
- "You are evolving NetLogo agent behavior for a food collection task. "
- "Current rule: " current-rule "\n"
- "Objective: Help agents efficiently find and collect food sources in the environment.\n"
- "Constraints: Use only valid NetLogo turtle commands (lt, rt, fd, bk, etc.). "
- "Keep rules concise (1-3 commands). Avoid complex conditionals.\n"
- "Performance context: Agents need to balance exploration and exploitation. "
- "Current generation: " generation "\n"
- "Evolution history: " (summarize-evolution-history) "\n"
- "Generate an improved version of the current rule that maintains valid NetLogo syntax "
- "and helps agents find food more effectively. Return only the NetLogo code, no explanations."
- )
-
- let evolved-rule ""
- carefully [
- set evolved-rule llm:chat mutation-prompt
- ; Clean up the response to extract just the code
- set evolved-rule trim evolved-rule
- if length evolved-rule > 100 [
- ; If response is too long, truncate or use fallback
- set evolved-rule current-rule
- ]
- ; Record this evolution in history
- set evolution-history lput (list current-rule evolved-rule generation) evolution-history
- if length evolution-history > evolution-history-limit [
- set evolution-history but-first evolution-history
- ]
- ] [
- ; If LLM call fails, use fallback mutation
- set evolved-rule fallback-mutate current-rule
- if verbose? [
- print (word "LLM mutation failed, using fallback. Error: " error-message)
- ]
- ]
-
- report evolved-rule
-end
-
-to-report summarize-evolution-history
- if length evolution-history = 0 [
- report "No previous evolution history."
- ]
-
- let summary "Recent evolutions:\n"
- let recent-history sublist evolution-history (max list 0 (length evolution-history - 3)) length evolution-history
-
- foreach recent-history [ entry ->
- let old-rule first entry
- let new-rule item 1 entry
- let gen item 2 entry
- set summary (word summary "Gen " gen ": " old-rule " -> " new-rule "\n")
- ]
-
- report summary
-end
-
-to-report fallback-mutate [current-rule]
- ; Simple fallback mutation when LLM is unavailable
- let mutations (list
- "lt random 30 fd 1"
- "rt random 30 fd 1"
- "lt random 10 rt random 10 fd 2"
- "if any? food-sources in-cone 5 30 [ fd 2 ] [ lt random 45 fd 1 ]"
- "rt random 45 fd 1 if random 100 < 20 [ lt 90 ]"
- )
- report one-of mutations
-end
-
-to eat-food
- if any? food-sources-here [
- ask one-of food-sources-here [
- die
- ]
- set energy energy + 1
- set food-collected food-collected + 1
- ]
-end
-
-to replenish-food
- if count food-sources < num-food-sources [
- spawn-food (num-food-sources - count food-sources)
- ]
-end
-
-;;; Selection and Statistics
-
-to-report select-agents
- if selection = "tournament" [
- report tournament-selection num-parents tournament-size
- ]
- if selection = "fitness-prop" [
- report fitness-proportional-selection num-parents
- ]
- report n-of num-parents llm-agents ; fallback
-end
-
-to-report tournament-selection [num-to-select tournament-size]
- let selected []
- repeat num-to-select [
- let tournament n-of tournament-size llm-agents
- let winner max-one-of tournament [fitness]
- set selected lput winner selected
- ]
- report selected
-end
-
-to-report fitness-proportional-selection [num-to-select]
- let total-fitness sum [fitness] of llm-agents
- if total-fitness = 0 [ report n-of num-to-select llm-agents ]
-
- let selected []
- repeat num-to-select [
- let random-val random-float total-fitness
- let cumulative-fitness 0
- let chosen nobody
- ask llm-agents [
- set cumulative-fitness cumulative-fitness + fitness
- if chosen = nobody and cumulative-fitness >= random-val [
- set chosen self
- ]
- ]
- if chosen != nobody [
- set selected lput chosen selected
- ]
- ]
- report selected
-end
-
-to update-generation-stats
- if any? llm-agents [
- let current-best max-one-of llm-agents [fitness]
- ask current-best [
- if fitness > best-rule-fitness [
- set best-rule rule
- set best-rule-fitness fitness
- ]
- ]
- ]
-end
-
-to-report agent-dict [agent-set]
- let dict table:make
- ask agent-set [
- table:put dict who (list rule fitness food-collected lifetime parent-id)
- ]
- report dict
-end
-
-;;; Helpers and Observable Reporters
-
-to-report fitness
- report energy
-end
-
-to-report mean-fitness
- report mean [fitness] of llm-agents
-end
-
-to-report get-observation
- let dist 7
- let angle 20
- let obs []
- foreach [-20 40 -20] [a ->
- rt a
- set obs lput (get-in-cone dist angle) obs
- ]
- report obs
-end
-
-to-report get-in-cone [dist angle]
- let val 0
- let cone other food-sources in-cone dist angle
- let f min-one-of cone with [is-food-source? self] [distance myself]
- if f != nobody [
- set val distance f
- ]
- report val
-end
-
-to-report get-generation-metrics
- let keys ["generation" "best rule" "mean fitness" "best fitness" "mean food" "error log"]
- let values ifelse-value any? llm-agents [
- (list
- generation
- best-rule
- mean-fitness
- max [fitness] of llm-agents
- mean [food-collected] of llm-agents
- error-log)
- ] [
- (list generation "na" 0 0 0 [])
- ]
- report fp:zip keys values
-end
-
-;;; Logging (simplified - remove dependency on external logging system)
-
-to setup-logger [params]
- ; Simplified logging setup
- print "Logger initialized"
-end
-
-to log-metrics [dicts]
- ; Simplified logging
- if verbose? [
- print (word "Generation " generation " completed")
- print (word "Best fitness: " best-rule-fitness)
- print (word "Mean fitness: " mean-fitness)
- ]
-end
-
-;;; Plotting
-
-to do-plotting
- if ticks mod ticks-per-generation = 0 [
- set-current-plot "Mean Energy of Agents"
- set-current-plot-pen "Mean Energy"
- plotxy generation mean-fitness
- set-current-plot-pen "Max Energy"
- plotxy generation max [energy] of llm-agents
- ]
-end
-
-;;; Configuration loading (simplified)
-
-to setup-params-default
- ; Default parameters - can be expanded
-end
-
-;;; Utility functions
-
-to-report trim [str]
- ; Simple trim function - remove leading/trailing whitespace
- let result str
- while [length result > 0 and first result = " "] [
- set result but-first result
- ]
- while [length result > 0 and last result = " "] [
- set result but-last result
- ]
- report result
-end
-
-;;; Write configuration helper
-
-to write-prompt-config [prompt-type prompt-name]
- ; Placeholder for configuration writing
- if verbose? [
- print (word "Using prompt type: " prompt-type " with name: " prompt-name)
- ]
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-210
-10
-647
-448
--1
--1
-13.0
-1
-10
-1
-1
-1
-0
-1
-1
-1
--16
-16
--16
-16
-1
-1
-1
-ticks
-30.0
-
-BUTTON
-20
-190
-90
-223
-NIL
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-100
-190
-170
-223
-NIL
-go
-T
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-SLIDER
-20
-20
-195
-53
-num-llm-agents
-num-llm-agents
-0
-25
-10.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-60
-195
-93
-num-food-sources
-num-food-sources
-0
-100
-30.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-100
-195
-133
-ticks-per-generation
-ticks-per-generation
-1
-2000
-500.0
-1
-1
-NIL
-HORIZONTAL
-
-SWITCH
-20
-140
-195
-173
-logging?
-logging?
-0
-1
--1000
-
-SWITCH
-20
-240
-195
-273
-verbose?
-verbose?
-1
-1
--1000
-
-CHOOSER
-20
-320
-195
-365
-selection
-selection
-"tournament" "fitness-prop"
-0
-
-SLIDER
-20
-370
-195
-403
-num-parents
-num-parents
-0
-10
-2.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-410
-195
-443
-tournament-size
-tournament-size
-0
-50
-8.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-450
-195
-483
-selection-pressure
-selection-pressure
-0
-1
-0.8
-0.01
-1
-NIL
-HORIZONTAL
-
-SWITCH
-20
-280
-195
-313
-use-config-file?
-use-config-file?
-1
-1
--1000
-
-INPUTBOX
-210
-470
-385
-530
-config-file
-default
-1
-0
-String
-
-INPUTBOX
-400
-470
-575
-530
-llm-config-file
-demos/config
-1
-0
-String
-
-CHOOSER
-400
-370
-575
-415
-llm-provider
-llm-provider
-"openai" "anthropic" "gemini" "ollama"
-0
-
-INPUTBOX
-400
-420
-575
-480
-llm-model
-gpt-4o-mini
-1
-0
-String
-
-INPUTBOX
-580
-370
-755
-430
-llm-api-key
-your-api-key-here
-1
-0
-String
-
-SLIDER
-580
-440
-755
-473
-evolution-history-limit
-evolution-history-limit
-5
-50
-10.0
-1
-1
-NIL
-HORIZONTAL
-
-PLOT
-680
-60
-1090
-350
-Mean Energy of Agents
-generation
-energy
-0.0
-5.0
-0.0
-10.0
-true
-true
-"" ""
-PENS
-"Mean Energy" 1.0 0 -817084 true "" ""
-"Max Energy" 1.0 0 -13345367 true "" ""
-
-MONITOR
-680
-10
-757
-55
-NIL
-generation
-17
-1
-11
-
-MONITOR
-760
-10
-857
-55
-NIL
-best-rule-fitness
-17
-1
-11
-
-TEXTBOX
-400
-540
-750
-582
-LLM Configuration: Set your provider, model, and API key. Use config.txt for persistent settings.
-11
-0.0
-1
-
-TEXTBOX
-20
-500
-370
-550
-Evolution Parameters: Configure selection method, population size, and tournament settings for genetic algorithm.
-11
-0.0
-1
-
-@#$#@#$#@
-## WHAT IS IT?
-
-This model demonstrates code evolution using Large Language Models (LLMs) instead of traditional genetic programming. Agents (turtles) evolve NetLogo code rules for food collection through LLM-guided mutations, showing how AI can be used to evolve agent behaviors.
-
-## HOW IT WORKS
-
-Instead of using Python-based mutations, this model uses the NetLogo LLM extension to evolve agent behaviors:
-
-1. **Agents**: Each turtle has a NetLogo rule (code) that controls its movement
-2. **Environment**: Food sources are scattered randomly across the world
-3. **Fitness**: Agents are scored based on how much food they collect
-4. **Evolution**: Each generation, the best-performing agents are selected to reproduce
-5. **LLM Mutation**: Instead of random code changes, an LLM generates improved versions of the code based on:
- - Current performance
- - Evolution history
- - Objective constraints
- - NetLogo syntax requirements
-
-The LLM acts as an intelligent mutation operator, understanding both the goal (food collection) and the constraints (valid NetLogo syntax) to generate meaningful code improvements.
-
-## HOW TO USE IT
-
-1. **Setup LLM Configuration**:
- - Choose your LLM provider (OpenAI, Anthropic, Gemini, or Ollama)
- - Set your model (e.g., gpt-4o-mini, claude-3-haiku)
- - Provide API key (not needed for Ollama)
- - Optionally use a config file for persistent settings
-
-2. **Configure Evolution Parameters**:
- - Set number of agents and food sources
- - Choose selection method (tournament or fitness-proportional)
- - Adjust tournament size and selection pressure
-
-3. **Run the Simulation**:
- - Click SETUP to initialize the model
- - Click GO to start the evolution process
- - Watch as agents evolve better food collection strategies
-
-## THINGS TO NOTICE
-
-- **Code Evolution**: Watch how the agent rules become more sophisticated over generations
-- **Fitness Improvement**: The plot shows how mean and max fitness improve over time
-- **LLM Intelligence**: Unlike random mutations, LLM-generated code maintains semantic meaning
-- **Fallback Mechanism**: If LLM calls fail, the system uses simple fallback mutations
-- **Evolution History**: The LLM considers previous evolution attempts to make better changes
-
-## THINGS TO TRY
-
-- **Different LLM Providers**: Compare how different models (GPT-4, Claude, Gemini) evolve code
-- **Varying Population**: Try different numbers of agents and see how it affects evolution speed
-- **Selection Methods**: Compare tournament vs fitness-proportional selection
-- **History Limits**: Adjust how much evolution history the LLM considers
-- **Environment Changes**: Modify food distribution patterns and see how agents adapt
-
-## EXTENDING THE MODEL
-
-- **Multi-objective Evolution**: Add multiple fitness criteria (efficiency, energy conservation)
-- **Interactive Evolution**: Allow users to guide evolution with feedback
-- **Code Analysis**: Have the LLM explain why certain mutations are beneficial
-- **Hybrid Approaches**: Combine LLM mutations with traditional genetic operators
-- **Dynamic Environments**: Change food patterns and see how quickly agents adapt
-
-## NETLOGO FEATURES
-
-This model showcases several advanced NetLogo features:
-
-- **Extension Integration**: Uses the LLM extension for AI-powered code generation
-- **Dynamic Code Execution**: Agents run dynamically generated NetLogo code
-- **Error Handling**: Robust error handling for invalid generated code
-- **Async Operations**: Supports both synchronous and asynchronous LLM calls
-- **Multi-agent Evolution**: Each agent maintains its own evolutionary lineage
-
-## RELATED MODELS
-
-- Traditional Genetic Programming models in NetLogo
-- Evolutionary Algorithm examples
-- Machine Learning and AI demonstrations
-- Agent-based modeling with learning
-
-## CREDITS AND REFERENCES
-
-This model demonstrates the integration of Large Language Models with evolutionary computation in NetLogo. It builds upon traditional genetic programming concepts while leveraging modern AI capabilities for more intelligent code evolution.
-
-The LLM extension enables seamless integration with multiple AI providers, making advanced AI capabilities accessible within NetLogo's agent-based modeling environment.
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-airplane
-true
-0
-Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15
-
-arrow
-true
-0
-Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150
-
-box
-false
-0
-Polygon -7500403 true true 150 285 285 225 285 75 150 135
-Polygon -7500403 true true 150 135 15 75 150 15 285 75
-Polygon -7500403 true true 15 75 15 225 150 285 150 135
-Line -16777216 false 150 285 150 135
-Line -16777216 false 150 135 15 75
-Line -16777216 false 150 135 285 75
-
-bug
-true
-0
-Circle -7500403 true true 96 182 108
-Circle -7500403 true true 110 127 80
-Circle -7500403 true true 110 75 80
-Line -7500403 true 150 100 80 30
-Line -7500403 true 150 100 220 30
-
-butterfly
-true
-0
-Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
-Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
-Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
-Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
-Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
-Circle -16777216 true false 135 90 30
-Line -16777216 false 150 105 195 60
-Line -16777216 false 150 105 105 60
-
-car
-false
-0
-Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
-Circle -16777216 true false 180 180 90
-Circle -16777216 true false 30 180 90
-Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
-Circle -7500403 true true 47 195 58
-Circle -7500403 true true 195 195 58
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-
-circle 2
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-
-cow
-false
-0
-Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
-Polygon -7500403 true true 73 210 86 251 62 249 48 208
-Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123
-
-cylinder
-false
-0
-Circle -7500403 true true 0 0 300
-
-dot
-false
-0
-Circle -7500403 true true 90 90 120
-
-face happy
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240
-
-face neutral
-false
-0
-Circle -7500403 true true 8 7 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Rectangle -16777216 true false 60 195 240 225
-
-face sad
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183
-
-fish
-false
-0
-Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
-Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
-Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
-Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
-Circle -16777216 true false 215 106 30
-
-flag
-false
-0
-Rectangle -7500403 true true 60 15 75 300
-Polygon -7500403 true true 90 150 270 90 90 30
-Line -7500403 true 75 135 90 135
-Line -7500403 true 75 45 90 45
-
-flower
-false
-0
-Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
-Circle -7500403 true true 85 132 38
-Circle -7500403 true true 130 147 38
-Circle -7500403 true true 192 85 38
-Circle -7500403 true true 85 40 38
-Circle -7500403 true true 177 40 38
-Circle -7500403 true true 177 132 38
-Circle -7500403 true true 70 85 38
-Circle -7500403 true true 130 25 38
-Circle -7500403 true true 96 51 108
-Circle -16777216 true false 113 68 74
-Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
-Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240
-
-house
-false
-0
-Rectangle -7500403 true true 45 120 255 285
-Rectangle -16777216 true false 120 210 180 285
-Polygon -7500403 true true 15 120 150 15 285 120
-Line -16777216 false 30 120 270 120
-
-leaf
-false
-0
-Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
-Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195
-
-line
-true
-0
-Line -7500403 true 150 0 150 300
-
-line half
-true
-0
-Line -7500403 true 150 0 150 150
-
-pentagon
-false
-0
-Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120
-
-person
-false
-0
-Circle -7500403 true true 110 5 80
-Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
-Rectangle -7500403 true true 127 79 172 94
-Polygon -7500403 true true 195 90 240 150 225 180 165 105
-Polygon -7500403 true true 105 90 60 150 75 180 135 105
-
-plant
-false
-0
-Rectangle -7500403 true true 135 90 165 300
-Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
-Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
-Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
-Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
-Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
-Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
-Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90
-
-sheep
-false
-15
-Circle -1 true true 203 65 88
-Circle -1 true true 70 65 162
-Circle -1 true true 150 105 120
-Polygon -7500403 true false 218 120 240 165 255 165 278 120
-Circle -7500403 true false 214 72 67
-Rectangle -1 true true 164 223 179 298
-Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
-Circle -1 true true 3 83 150
-Rectangle -1 true true 65 221 80 296
-Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
-Polygon -7500403 true false 276 85 285 105 302 99 294 83
-Polygon -7500403 true false 219 85 210 105 193 99 201 83
-
-square
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-
-square 2
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-Rectangle -16777216 true false 60 60 240 240
-
-star
-false
-0
-Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108
-
-target
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-Circle -7500403 true true 60 60 180
-Circle -16777216 true false 90 90 120
-Circle -7500403 true true 120 120 60
-
-tree
-false
-0
-Circle -7500403 true true 118 3 94
-Rectangle -6459832 true false 120 195 180 300
-Circle -7500403 true true 65 21 108
-Circle -7500403 true true 116 41 127
-Circle -7500403 true true 45 90 120
-Circle -7500403 true true 104 74 152
-
-triangle
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-
-triangle 2
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-Polygon -16777216 true false 151 99 225 223 75 224
-
-truck
-false
-0
-Rectangle -7500403 true true 4 45 195 187
-Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
-Rectangle -1 true false 195 60 195 105
-Polygon -16777216 true false 238 112 252 141 219 141 218 112
-Circle -16777216 true false 234 174 42
-Rectangle -7500403 true true 181 185 214 194
-Circle -16777216 true false 144 174 42
-Circle -16777216 true false 24 174 42
-Circle -7500403 false true 24 174 42
-Circle -7500403 false true 144 174 42
-Circle -7500403 false true 234 174 42
-
-turtle
-true
-0
-Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
-Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
-Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
-Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
-Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
-Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99
-
-wheel
-false
-0
-Circle -7500403 true true 3 3 294
-Circle -16777216 true false 30 30 240
-Line -7500403 true 150 285 150 15
-Line -7500403 true 15 150 285 150
-Circle -7500403 true true 120 120 60
-Line -7500403 true 216 40 79 269
-Line -7500403 true 40 84 269 221
-Line -7500403 true 40 216 269 79
-Line -7500403 true 84 40 221 269
-
-wolf
-false
-0
-Polygon -16777216 true false 253 133 245 131 245 133
-Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
-
-x
-false
-0
-Polygon -7500403 true true 270 75 225 30 30 225 75 270
-Polygon -7500403 true true 30 75 75 30 270 225 225 270
-
-@#$#@#$#@
-NetLogo 6.4.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/llm-color-sharing.nlogox.nlogo b/demos/old-version-files/llm-color-sharing.nlogox.nlogo
deleted file mode 100644
index 49f416a..0000000
--- a/demos/old-version-files/llm-color-sharing.nlogox.nlogo
+++ /dev/null
@@ -1,699 +0,0 @@
-extensions [llm table string]
-
-globals [
- colors
-]
-
-turtles-own [
- name
- favorite-color
- last-message
- conversation-knowledge
-]
-
-undirected-link-breed [connections connection]
-
-to setup
- clear-all
-
- ; Load LLM configuration
- llm:load-config "demos/config"
-
- set-default-shape turtles "person"
-
- let names ["Alice" "Ben" "Cindy" "David" "Emily" "Frank"
- "Gina" "Harry" "Isabella" "Jack" "Katie" "Liam"
- "Maggie" "Noah" "Olivia" "Patrick" "Quinn" "Rachel"
- "Samuel" "Tracy" "Ursula" "Vanessa" "William" "Xander"
- "Yvette" "Zack"]
-
- set colors ["red" "blue" "green" "yellow" "orange" "purple"]
-
- create-turtles num-agents [
- fd 10
- set size 2
- set name item who names
- set favorite-color one-of colors
- set color runresult favorite-color
- set last-message ""
- set conversation-knowledge table:make
-
- ; Connect to nearby agents
- create-connections-with min-n-of 2 other turtles [distance myself]
- ]
-
- ; Initialize each agent with their personality and goal
- ask turtles [
- set label (word name ": " favorite-color)
-
- ; Set up initial conversation history with personality
- llm:set-history (list
- (list "system" (word
- "You are " name " in a social network. "
- "Your favorite color is " favorite-color ". "
- "You are connected to: " (reduce [[s w] -> (word s ", " w)] [name] of link-neighbors) ". "
- "Your goal is to learn everyone's favorite colors through conversation. "
- "Be friendly and curious. Ask questions and share what you learn. "
- "Keep responses to 1-2 short sentences. "
- "When responding, format as JSON: {\"message\": \"your message\", \"learned\": {\"AgentName\": \"color\"}} "
- "Only include agents whose colors you've definitively learned in the 'learned' object."))
- )
- ]
-
- reset-ticks
-end
-
-to go
- ask turtles [
- ; Gather messages from neighbors
- let neighbor-messages ""
- ask link-neighbors with [last-message != ""] [
- set neighbor-messages (word neighbor-messages name ": " last-message "\n")
- ]
-
- ; Create prompt for this turn
- let current-prompt (word
- "Recent messages from your neighbors:\n" neighbor-messages
- "\nWhat would you like to say to learn more about everyone's favorite colors? "
- "Remember to respond in JSON format with 'message' and 'learned' fields.")
-
- ; Get LLM response
- carefully [
- let response llm:chat current-prompt
-
- ; Try to parse JSON response
- let parsed-response table:from-json response
-
- ; Extract message
- if table:has-key? parsed-response "message" [
- set last-message table:get parsed-response "message"
- set label word-wrap (word name ": " last-message) 25
- ]
-
- ; Update knowledge about other agents' colors
- if table:has-key? parsed-response "learned" [
- let learned-colors table:get parsed-response "learned"
- foreach table:to-list learned-colors [ color-pair ->
- table:put conversation-knowledge (first color-pair) (last color-pair)
- ]
- ]
-
- ] [
- ; Fallback if JSON parsing fails
- let response llm:chat current-prompt
- set last-message substring response 0 (min (list 50 (length response))) ; Just take first part as message
- set label word-wrap (word name ": " last-message) 25
- ]
- ]
-
- ; Update visual indicators based on learned knowledge
- ask turtles [
- ; Count how many colors this agent has learned
- let known-colors table:length conversation-knowledge
-
- ; Adjust turtle size to show learning progress
- set size 2 + (known-colors * 0.3)
-
- ; Show knowledge in a tooltip or separate display
- if show-knowledge? [
- let knowledge-text ""
- foreach table:to-list conversation-knowledge [ pair ->
- set knowledge-text (word knowledge-text (first pair) ":" (last pair) " ")
- ]
- if knowledge-text != "" [
- set label (word name "\n" knowledge-text)
- ]
- ]
- ]
-
- tick
-end
-
-to-report word-wrap [str len]
- let line ""
- let wrapped ""
- foreach (string:split-on " " str) [ w ->
- if length line + length w > len [
- set wrapped (word wrapped "\n" line)
- set line ""
- ]
- set line string:trim (word line " " w)
- ]
- report string:trim (word wrapped "\n" line)
-end
-
-; Reporter to check if all agents have learned all colors
-to-report all-knowledge-complete?
- let complete true
- ask turtles [
- ; Each agent should know about (num-agents - 1) other agents
- if table:length conversation-knowledge < (count turtles - 1) [
- set complete false
- ]
- ]
- report complete
-end
-
-; Display what each agent has learned
-to show-agent-knowledge
- ask turtles [
- print (word name "'s knowledge:")
- foreach table:to-list conversation-knowledge [ pair ->
- print (word " " (first pair) " likes " (last pair))
- ]
- print ""
- ]
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-383
-10
-1051
-679
--1
--1
-20.0
-1
-10
-1
-1
-1
-0
-0
-0
-1
--16
-16
--16
-16
-1
-1
-1
-ticks
-30.0
-
-BUTTON
-5
-45
-78
-78
-NIL
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-110
-45
-175
-78
-NIL
-go
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-SLIDER
-5
-10
-175
-43
-num-agents
-num-agents
-2
-10
-6.0
-1
-1
-NIL
-HORIZONTAL
-
-SWITCH
-200
-10
-350
-43
-show-knowledge?
-show-knowledge?
-1
-1
--1000
-
-BUTTON
-200
-50
-350
-83
-Show Agent Knowledge
-show-agent-knowledge
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-MONITOR
-5
-90
-175
-135
-Agents Created
-count turtles
-17
-1
-11
-
-MONITOR
-200
-90
-350
-135
-Average Knowledge
-mean [table:length conversation-knowledge] of turtles
-2
-1
-11
-
-TEXTBOX
-5
-145
-375
-225
-This demo shows agents using LLM to learn each other's favorite colors through conversation. Each agent has a name, favorite color, and can talk to connected neighbors. They use the LLM extension to generate contextual responses and track what they learn about others.
-11
-0.0
-1
-
-TEXTBOX
-5
-235
-375
-285
-Instructions:\n1. Click SETUP to create agents with random colors and connections\n2. Click GO to start conversations (agents will chat each tick)\n3. Toggle 'show-knowledge?' to see what each agent has learned\n4. Use 'Show Agent Knowledge' to print detailed learning to output
-11
-0.0
-1
-@#$#@#$#@
-## WHAT IS IT?
-
-This model demonstrates how NetLogo agents can use Large Language Models (LLMs) to engage in intelligent conversations and learn from each other. Each agent has a favorite color and tries to discover the favorite colors of all other agents in the network through natural conversation.
-
-## HOW IT WORKS
-
-1. **Agent Setup**: Each agent gets a name, favorite color, and connects to nearby agents
-2. **LLM Integration**: Agents use the LLM extension to generate contextual, intelligent responses
-3. **Learning Process**: Through conversation, agents track what they learn about others' preferences
-4. **Memory Management**: Each agent maintains its own conversation history and knowledge base
-
-The agents use structured JSON responses to separate their conversational messages from their internal knowledge tracking.
-
-## HOW TO USE IT
-
-1. **SETUP**: Creates agents with random names, colors, and network connections
-2. **GO**: Runs one conversation round - each agent talks to neighbors
-3. **num-agents**: Controls how many agents participate (2-10)
-4. **show-knowledge?**: Toggle to display what each agent has learned
-5. **Show Agent Knowledge**: Prints detailed learning information to the output area
-
-## THINGS TO NOTICE
-
-- Agents get larger as they learn more (size indicates knowledge)
-- Different LLM providers may generate different conversation styles
-- Some agents may be more effective at information gathering
-- Network topology affects information flow speed
-
-## THINGS TO TRY
-
-- Change the number of agents and observe learning dynamics
-- Try different LLM providers (OpenAI, Claude, Gemini, Ollama) in config.txt
-- Modify the system prompt to create different agent personalities
-- Add more colors or change the learning objective
-
-## EXTENDING THE MODEL
-
-- Add agent movement and dynamic network formation
-- Implement different conversation strategies or personalities
-- Track conversation efficiency metrics
-- Add visual indicators for information flow
-- Create specialized roles (gossips, introverts, etc.)
-
-## NETLOGO FEATURES
-
-- Uses the LLM extension for AI-powered agent behavior
-- Demonstrates per-agent conversation memory
-- Shows JSON parsing for structured LLM responses
-- Integrates table extension for knowledge storage
-- Uses link breeds for network visualization
-
-## RELATED MODELS
-
-- Communication networks in complex systems
-- Information diffusion models
-- Social learning simulations
-- Multi-agent conversation systems
-
-## CREDITS AND REFERENCES
-
-This model demonstrates the NetLogo LLM Extension capabilities for creating intelligent, conversational agents in agent-based models.
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-airplane
-true
-0
-Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15
-
-arrow
-true
-0
-Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150
-
-box
-false
-0
-Polygon -7500403 true true 150 285 285 225 285 75 150 135
-Polygon -7500403 true true 150 135 15 75 150 15 285 75
-Polygon -7500403 true true 15 75 15 225 150 285 150 135
-Line -16777216 false 150 285 150 135
-Line -16777216 false 150 135 15 75
-Line -16777216 false 150 135 285 75
-
-bug
-true
-0
-Circle -7500403 true true 96 182 108
-Circle -7500403 true true 110 127 80
-Circle -7500403 true true 110 75 80
-Line -7500403 true 150 100 80 30
-Line -7500403 true 150 100 220 30
-
-butterfly
-true
-0
-Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
-Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
-Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
-Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
-Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
-Circle -16777216 true false 135 90 30
-Line -16777216 false 150 105 195 60
-Line -16777216 false 150 105 105 60
-
-car
-false
-0
-Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
-Circle -16777216 true false 180 180 90
-Circle -16777216 true false 30 180 90
-Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
-Circle -7500403 true true 47 195 58
-Circle -7500403 true true 195 195 58
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-
-circle 2
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-
-cow
-false
-0
-Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
-Polygon -7500403 true true 73 210 86 251 62 249 48 208
-Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123
-
-cylinder
-false
-0
-Circle -7500403 true true 0 0 300
-
-dot
-false
-0
-Circle -7500403 true true 90 90 120
-
-face happy
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240
-
-face neutral
-false
-0
-Circle -7500403 true true 8 7 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Rectangle -16777216 true false 60 195 240 225
-
-face sad
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183
-
-fish
-false
-0
-Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
-Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
-Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
-Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
-Circle -16777216 true false 215 106 30
-
-flag
-false
-0
-Rectangle -7500403 true true 60 15 75 300
-Polygon -7500403 true true 90 150 270 90 90 30
-Line -7500403 true 75 135 90 135
-Line -7500403 true 75 45 90 45
-
-flower
-false
-0
-Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
-Circle -7500403 true true 85 132 38
-Circle -7500403 true true 130 147 38
-Circle -7500403 true true 192 85 38
-Circle -7500403 true true 85 40 38
-Circle -7500403 true true 177 40 38
-Circle -7500403 true true 177 132 38
-Circle -7500403 true true 70 85 38
-Circle -7500403 true true 130 25 38
-Circle -7500403 true true 96 51 108
-Circle -16777216 true false 113 68 74
-Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
-Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240
-
-house
-false
-0
-Rectangle -7500403 true true 45 120 255 285
-Rectangle -16777216 true false 120 210 180 285
-Polygon -7500403 true true 15 120 150 15 285 120
-Line -16777216 false 30 120 270 120
-
-leaf
-false
-0
-Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
-Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195
-
-line
-true
-0
-Line -7500403 true 150 0 150 300
-
-line half
-true
-0
-Line -7500403 true 150 0 150 150
-
-pentagon
-false
-0
-Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120
-
-person
-false
-0
-Circle -7500403 true true 110 5 80
-Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
-Rectangle -7500403 true true 127 79 172 94
-Polygon -7500403 true true 195 90 240 150 225 180 165 105
-Polygon -7500403 true true 105 90 60 150 75 180 135 105
-
-plant
-false
-0
-Rectangle -7500403 true true 135 90 165 300
-Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
-Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
-Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
-Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
-Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
-Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
-Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90
-
-sheep
-false
-15
-Circle -1 true true 203 65 88
-Circle -1 true true 70 65 162
-Circle -1 true true 150 105 120
-Polygon -7500403 true false 218 120 240 165 255 165 278 120
-Circle -7500403 true false 214 72 67
-Rectangle -1 true true 164 223 179 298
-Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
-Circle -1 true true 3 83 150
-Rectangle -1 true true 65 221 80 296
-Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
-Polygon -7500403 true false 276 85 285 105 302 99 294 83
-Polygon -7500403 true false 219 85 210 105 193 99 201 83
-
-square
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-
-square 2
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-Rectangle -16777216 true false 60 60 240 240
-
-star
-false
-0
-Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108
-
-target
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-Circle -7500403 true true 60 60 180
-Circle -16777216 true false 90 90 120
-Circle -7500403 true true 120 120 60
-
-tree
-false
-0
-Circle -7500403 true true 118 3 94
-Rectangle -6459832 true false 120 195 180 300
-Circle -7500403 true true 65 21 108
-Circle -7500403 true true 116 41 127
-Circle -7500403 true true 45 90 120
-Circle -7500403 true true 104 74 152
-
-triangle
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-
-triangle 2
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-Polygon -16777216 true false 151 99 225 223 75 224
-
-truck
-false
-0
-Rectangle -7500403 true true 4 45 195 187
-Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
-Rectangle -1 true false 195 60 195 105
-Polygon -16777216 true false 238 112 252 141 219 141 218 112
-Circle -16777216 true false 234 174 42
-Rectangle -7500403 true true 181 185 214 194
-Circle -16777216 true false 144 174 42
-Circle -16777216 true false 24 174 42
-Circle -7500403 false true 24 174 42
-Circle -7500403 false true 144 174 42
-Circle -7500403 false true 234 174 42
-
-turtle
-true
-0
-Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
-Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
-Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
-Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
-Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
-Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99
-
-wheel
-false
-0
-Circle -7500403 true true 3 3 294
-Circle -16777216 true false 30 30 240
-Line -7500403 true 150 285 150 15
-Line -7500403 true 15 150 285 150
-Circle -7500403 true true 120 120 60
-Line -7500403 true 216 40 79 269
-Line -7500403 true 40 84 269 221
-Line -7500403 true 40 216 269 79
-Line -7500403 true 84 40 221 269
-
-wolf
-false
-0
-Polygon -16777216 true false 253 133 245 131 245 133
-Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
-Polygon -7500403 true true -1 195 14 180 36 166 40 153 53 140 82 131 134 133 159 126 188 115 227 108 236 102 238 98 268 86 269 92 281 87 269 103 269 113
-
-x
-false
-0
-Polygon -7500403 true true 270 75 225 30 30 225 75 270
-Polygon -7500403 true true 30 75 75 30 270 225 225 270
-@#$#@#$#@
-NetLogo 6.3.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/minimal-llm-evolution.nlogo b/demos/old-version-files/minimal-llm-evolution.nlogo
deleted file mode 100644
index ea98642..0000000
--- a/demos/old-version-files/minimal-llm-evolution.nlogo
+++ /dev/null
@@ -1,560 +0,0 @@
-extensions [ llm ]
-
-globals [
- generation
- best-fitness
- best-rule
-]
-
-breed [agents agent]
-breed [foods food]
-
-agents-own [
- rule
- energy
-]
-
-to setup
- clear-all
-
- ; Load LLM config
- llm:load-config "demos/config"
-
- set generation 0
- set best-fitness 0
- set best-rule "fd 1"
-
- ; Create agents
- create-agents 10 [
- set color red
- setxy random-xcor random-ycor
- set rule "fd 1 rt random 45"
- set energy 0
- ]
-
- ; Create food
- create-foods 20 [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
-
- reset-ticks
-end
-
-to go
- ; Agents execute their rules
- ask agents [
- carefully [ run rule ] [ ]
- eat-food
- ]
-
- ; Evolution every 100 ticks
- if ticks > 0 and ticks mod 100 = 0 [
- evolve
- ]
-
- ; Replenish food
- if count foods < 20 [
- create-foods (20 - count foods) [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
- ]
-
- tick
-end
-
-to eat-food
- if any? foods-here [
- ask one-of foods-here [ die ]
- set energy energy + 1
- ]
-end
-
-to evolve
- set generation generation + 1
- print (word "Generation " generation)
-
- ; Find best agent
- let best-agent max-one-of agents [energy]
- if best-agent != nobody [
- ask best-agent [
- if energy > best-fitness [
- set best-fitness energy
- set best-rule rule
- print (word "New best: " rule " fitness: " energy)
- ]
- ]
- ]
-
- ; Kill worst agents and replace with mutated versions
- let worst-agents min-n-of 3 agents [energy]
- ask worst-agents [
- set rule mutate-rule [rule] of best-agent
- set energy 0
- ]
-
- ; Reset all energy
- ask agents [ set energy 0 ]
-end
-
-to-report mutate-rule [parent-rule]
- let prompt (word "Improve this NetLogo rule for finding food: " parent-rule
- " Return only NetLogo code, one line, using: fd, bk, rt, lt, random")
-
- let new-rule parent-rule
- carefully [
- set new-rule llm:chat prompt
- ] [
- ; Fallback if LLM fails
- set new-rule one-of ["fd 1 rt random 60" "fd 2 lt random 45" "fd 1"]
- ]
-
- report new-rule
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-210
-10
-647
-448
--1
--1
-13.0
-1
-10
-1
-1
-1
-0
-1
-1
-1
--16
-16
--16
-16
-1
-1
-1
-ticks
-30.0
-
-BUTTON
-20
-20
-86
-53
-setup
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-96
-20
-159
-53
-go
-go
-T
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-MONITOR
-20
-70
-120
-115
-Generation
-generation
-17
-1
-11
-
-MONITOR
-20
-125
-120
-170
-Best Fitness
-best-fitness
-17
-1
-11
-
-MONITOR
-20
-180
-190
-225
-Best Rule
-best-rule
-17
-1
-11
-
-@#$#@#$#@
-## WHAT IS IT?
-
-Minimal agent code evolution using the NetLogo LLM extension.
-
-## HOW IT WORKS
-
-- Red agents move using NetLogo code rules
-- They collect green food to gain energy
-- Every 100 ticks, the worst agents get new rules evolved from the best agent using an LLM
-- The LLM improves the code to be better at finding food
-
-## HOW TO USE IT
-
-1. Make sure config.txt has your LLM settings
-2. Click SETUP
-3. Click GO
-4. Watch agents evolve better movement rules
-
-## NETLOGO FEATURES
-
-Uses the custom LLM extension to evolve code through natural language prompts.
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-airplane
-true
-0
-Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15
-
-arrow
-true
-0
-Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150
-
-box
-false
-0
-Polygon -7500403 true true 150 285 285 225 285 75 150 135
-Polygon -7500403 true true 150 135 15 75 150 15 285 75
-Polygon -7500403 true true 15 75 15 225 150 285 150 135
-Line -16777216 false 150 285 150 135
-Line -16777216 false 150 135 15 75
-Line -16777216 false 150 135 285 75
-
-bug
-true
-0
-Circle -7500403 true true 96 182 108
-Circle -7500403 true true 110 127 80
-Circle -7500403 true true 110 75 80
-Line -7500403 true 150 100 80 30
-Line -7500403 true 150 100 220 30
-
-butterfly
-true
-0
-Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
-Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
-Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
-Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
-Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
-Circle -16777216 true false 135 90 30
-Line -16777216 false 150 105 195 60
-Line -16777216 false 150 105 105 60
-
-car
-false
-0
-Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
-Circle -16777216 true false 180 180 90
-Circle -16777216 true false 30 180 90
-Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
-Circle -7500403 true true 47 195 58
-Circle -7500403 true true 195 195 58
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-
-circle 2
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-
-cow
-false
-0
-Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
-Polygon -7500403 true true 73 210 86 251 62 249 48 208
-Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123
-
-cylinder
-false
-0
-Circle -7500403 true true 0 0 300
-
-dot
-false
-0
-Circle -7500403 true true 90 90 120
-
-face happy
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240
-
-face neutral
-false
-0
-Circle -7500403 true true 8 7 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Rectangle -16777216 true false 60 195 240 225
-
-face sad
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183
-
-fish
-false
-0
-Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
-Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
-Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
-Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
-Circle -16777216 true false 215 106 30
-
-flag
-false
-0
-Rectangle -7500403 true true 60 15 75 300
-Polygon -7500403 true true 90 150 270 90 90 30
-Line -7500403 true 75 135 90 135
-Line -7500403 true 75 45 90 45
-
-flower
-false
-0
-Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
-Circle -7500403 true true 85 132 38
-Circle -7500403 true true 130 147 38
-Circle -7500403 true true 192 85 38
-Circle -7500403 true true 85 40 38
-Circle -7500403 true true 177 40 38
-Circle -7500403 true true 177 132 38
-Circle -7500403 true true 70 85 38
-Circle -7500403 true true 130 25 38
-Circle -7500403 true true 96 51 108
-Circle -16777216 true false 113 68 74
-Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
-Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240
-
-house
-false
-0
-Rectangle -7500403 true true 45 120 255 285
-Rectangle -16777216 true false 120 210 180 285
-Polygon -7500403 true true 15 120 150 15 285 120
-Line -16777216 false 30 120 270 120
-
-leaf
-false
-0
-Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
-Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195
-
-line
-true
-0
-Line -7500403 true 150 0 150 300
-
-line half
-true
-0
-Line -7500403 true 150 0 150 150
-
-pentagon
-false
-0
-Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120
-
-person
-false
-0
-Circle -7500403 true true 110 5 80
-Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
-Rectangle -7500403 true true 127 79 172 94
-Polygon -7500403 true true 195 90 240 150 225 180 165 105
-Polygon -7500403 true true 105 90 60 150 75 180 135 105
-
-plant
-false
-0
-Rectangle -7500403 true true 135 90 165 300
-Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
-Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
-Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
-Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
-Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
-Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
-Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90
-
-sheep
-false
-15
-Circle -1 true true 203 65 88
-Circle -1 true true 70 65 162
-Circle -1 true true 150 105 120
-Polygon -7500403 true false 218 120 240 165 255 165 278 120
-Circle -7500403 true false 214 72 67
-Rectangle -1 true true 164 223 179 298
-Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
-Circle -1 true true 3 83 150
-Rectangle -1 true true 65 221 80 296
-Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
-Polygon -7500403 true false 276 85 285 105 302 99 294 83
-Polygon -7500403 true false 219 85 210 105 193 99 201 83
-
-square
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-
-square 2
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-Rectangle -16777216 true false 60 60 240 240
-
-star
-false
-0
-Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108
-
-target
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-Circle -7500403 true true 60 60 180
-Circle -16777216 true false 90 90 120
-Circle -7500403 true true 120 120 60
-
-tree
-false
-0
-Circle -7500403 true true 118 3 94
-Rectangle -6459832 true false 120 195 180 300
-Circle -7500403 true true 65 21 108
-Circle -7500403 true true 116 41 127
-Circle -7500403 true true 45 90 120
-Circle -7500403 true true 104 74 152
-
-triangle
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-
-triangle 2
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-Polygon -16777216 true false 151 99 225 223 75 224
-
-truck
-false
-0
-Rectangle -7500403 true true 4 45 195 187
-Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
-Rectangle -1 true false 195 60 195 105
-Polygon -16777216 true false 238 112 252 141 219 141 218 112
-Circle -16777216 true false 234 174 42
-Rectangle -7500403 true true 181 185 214 194
-Circle -16777216 true false 144 174 42
-Circle -16777216 true false 24 174 42
-Circle -7500403 false true 24 174 42
-Circle -7500403 false true 144 174 42
-Circle -7500403 false true 234 174 42
-
-turtle
-true
-0
-Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
-Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
-Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
-Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
-Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
-Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99
-
-wheel
-false
-0
-Circle -7500403 true true 3 3 294
-Circle -16777216 true false 30 30 240
-Line -7500403 true 150 285 150 15
-Line -7500403 true 15 150 285 150
-Circle -7500403 true true 120 120 60
-Line -7500403 true 216 40 79 269
-Line -7500403 true 40 84 269 221
-Line -7500403 true 40 216 269 79
-Line -7500403 true 84 40 221 269
-
-wolf
-false
-0
-Polygon -16777216 true false 253 133 245 131 245 133
-Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
-Polygon -7500403 true true -1 195 14 180 36 166 40 153 53 140 82 131 134 133 159 126 188 115 227 108 236 102 238 98 268 86 269 92 281 87 269 103 269 113
-
-x
-false
-0
-Polygon -7500403 true true 270 75 225 30 30 225 75 270
-Polygon -7500403 true true 30 75 75 30 270 225 225 270
-@#$#@#$#@
-NetLogo 6.4.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/simple-collection-env-with-templates.nlogo b/demos/old-version-files/simple-collection-env-with-templates.nlogo
deleted file mode 100644
index 8d2d5f3..0000000
--- a/demos/old-version-files/simple-collection-env-with-templates.nlogo
+++ /dev/null
@@ -1,287 +0,0 @@
-extensions [ llm table fp rnd ]
-
-globals [
- generation
- init-rule
- generation-stats
- best-rule
- best-rule-fitness
- error-log
- init-pseudocode
-]
-
-breed [llm-agents llm-agent]
-breed [food-sources food-source]
-
-llm-agents-own [
- input ;; observation vector
- rule ;; current rule (llm-generated)
- energy ;; current score
- lifetime ;; age of the agent (in generations)
- food-collected ;; total food agent gathered
- parent-id ;; who number of parent
- parent-rule ;; parent rule
- pseudocode ;; descriptive text rule
- parent-pseudocode ;; pseudocode associated with the parent
-]
-
-;;; Setup Procedures
-
-to setup
- clear-all
-
- ; Configure LLM for code evolution (replace with your preferred provider)
- llm:set-provider "openai" ; or "anthropic", "gemini", etc.
- llm:set-model "gpt-4" ; or your preferred model
-
- set init-rule "lt random 20 rt random 20 fd 1"
- set init-pseudocode "Take left turn randomly within 0-20 degrees, then take right turn randomly within 0-20 degrees and move forward 1"
-
- set generation-stats []
- set error-log []
- set best-rule-fitness 0
-
- spawn-food 30 ; num-food-sources
- setup-llm-agents
- reset-ticks
-end
-
-to setup-llm-agents
- create-llm-agents 10 [ ; num-llm-agents
- set color red
- setxy random-xcor random-ycor
- set rule init-rule
- set parent-id "na"
- set parent-rule "na"
- set pseudocode init-pseudocode
- set parent-pseudocode "na"
- init-agent-params
- ]
-end
-
-to init-agent-params
- set energy 0
- set food-collected 0
- set lifetime 0
-end
-
-to spawn-food [num]
- create-food-sources num [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
-end
-
-;;; Go Procedures
-
-to go
- ask llm-agents [
- set lifetime lifetime + 1
- set input get-observation
- run-rule
- eat-food
- ]
- evolve-agents
- replenish-food
- tick
-end
-
-to run-rule
- carefully [
- run rule
- ] [
- let error-info (word
- "ERROR WHILE RUNNING RULE: " rule
- " | Agent: " who
- " | Tick: " ticks
- " | Fitness: " fitness
- " | Error: " error-message
- )
- print error-info
- set error-log lput error-info error-log
- ]
-end
-
-to evolve-agents
- if ticks >= 1 and ticks mod 500 = 0 [ ; ticks-per-generation
- print word "\nGeneration: " generation
-
- let parents select-best-agents 2 ; select top 2 agents
- let kill-num length parents
-
- foreach parents [ parent ->
- ask parent [
- let my-parent-id who
- let my-rule rule
- let my-pseudocode pseudocode
- hatch 1 [
- set parent-id my-parent-id
- set parent-rule my-rule
- set parent-pseudocode my-pseudocode
-
- ; NEW: Use LLM template instead of Python mutation
- set rule mutate-rule-with-llm my-rule
-
- init-agent-params
- ]
- ]
- ]
-
- ; Remove worst performers
- ask min-n-of kill-num llm-agents [fitness] [ die ]
-
- ; Reset for next generation
- ask llm-agents [
- set food-collected 0
- set energy 0
- ]
-
- set generation generation + 1
- set error-log []
- ]
-end
-
-; NEW: LLM-based mutation using templates
-to-report mutate-rule-with-llm [current-rule]
- ; Track code evolution in conversation history
- llm:chat (word "CODE_VERSION: " current-rule)
-
- ; Get the agent's code evolution history
- let code-history get-code-evolution-history
-
- ; Use template to evolve the code
- let new-rule llm:chat-with-template "demos/code-evolution-template.yaml" (list
- ["current_code" current-rule]
- ["code_history" code-history]
- ["objective" "improve food collection efficiency and movement strategy"]
- ["constraints" "only use NetLogo movement commands: fd, bk, lt, rt, random"]
- ["performance_notes" (word "current fitness: " fitness " | food collected: " food-collected)]
- )
-
- ; Clean up the response (remove any extra text)
- set new-rule clean-code-response new-rule
-
- report new-rule
-end
-
-; Extract code evolution history from conversation
-to-report get-code-evolution-history
- let history llm:history
- let code-versions []
- foreach history [ msg ->
- let role item 0 msg
- let content item 1 msg
- if role = "user" and (substring content 0 13) = "CODE_VERSION:" [
- set code-versions lput (substring content 14 (length content)) code-versions
- ]
- ]
-
- ; Format as string for template
- ifelse length code-versions > 0 [
- let formatted-history ""
- let version-num 1
- foreach code-versions [ version ->
- set formatted-history (word formatted-history "v" version-num ": " version "\n")
- set version-num version-num + 1
- ]
- report formatted-history
- ] [
- report "No previous versions"
- ]
-end
-
-; Clean up LLM response to extract just the NetLogo code
-to-report clean-code-response [response]
- ; Remove common prefixes/suffixes that LLMs might add
- let cleaned response
-
- ; Remove newlines and extra spaces
- set cleaned reduce word (but-first but-last (word " " cleaned " "))
-
- ; If it looks like it has explanatory text, try to extract just the code
- ; This is a simple heuristic - you might need to adjust based on your LLM
- if (position ":" cleaned) != false [
- let colon-pos position ":" cleaned
- if colon-pos < 50 [ ; if colon is near the beginning, skip to after it
- set cleaned substring cleaned (colon-pos + 1) (length cleaned)
- ]
- ]
-
- ; Trim whitespace
- while [first cleaned = " "] [ set cleaned substring cleaned 1 (length cleaned) ]
- while [last cleaned = " "] [ set cleaned substring cleaned 0 (length cleaned - 1) ]
-
- report cleaned
-end
-
-to select-best-agents [num-agents]
- let best-agents max-n-of num-agents llm-agents [fitness]
- report sort-on [fitness] best-agents
-end
-
-to eat-food
- if any? food-sources-here [
- ask one-of food-sources-here [
- die
- ]
- set energy energy + 1
- set food-collected food-collected + 1
- ]
-end
-
-to replenish-food
- if count food-sources < 30 [ ; num-food-sources
- spawn-food (30 - count food-sources)
- ]
-end
-
-;;; Helpers and Observable Reporters
-
-to-report fitness
- report energy
-end
-
-to-report mean-fitness
- report mean [fitness] of llm-agents
-end
-
-to-report get-observation
- let dist 7
- let angle 20
- let obs []
- ;; obs order is [left-cone right-cone center-cone]
- foreach [-20 40 -20] [a ->
- rt a
- set obs lput (get-in-cone dist angle) obs
- ]
- report obs
-end
-
-to-report get-in-cone [dist angle]
- let val 0
- let cone other food-sources in-cone dist angle
- let f min-one-of cone with [is-food-source? self] [distance myself]
- if f != nobody [
- set val distance f
- ]
- report val
-end
-
-; Test function to demonstrate template usage
-to test-template-evolution
- ; Create a test agent and evolve its code
- create-llm-agents 1 [
- set rule "fd 1"
- set energy 5
- set food-collected 3
-
- print (word "Original rule: " rule)
-
- let evolved-rule mutate-rule-with-llm rule
- print (word "Evolved rule: " evolved-rule)
-
- die ; clean up test agent
- ]
-end
diff --git a/demos/old-version-files/simple-collection-env.nlogo b/demos/old-version-files/simple-collection-env.nlogo
deleted file mode 100644
index e7dbbdd..0000000
--- a/demos/old-version-files/simple-collection-env.nlogo
+++ /dev/null
@@ -1,1490 +0,0 @@
-extensions [ py table fp rnd ]
-
-__includes [
- "env_utils/evolution.nls"
- "env_utils/logging.nls"
- "env_utils/prompt_config.nls"
- "config/simple-collection-config.nls"
-]
-
-globals [
- generation
- init-rule
- generation-stats
- best-rule
- best-rule-fitness
- error-log
- init-pseudocode
-]
-
-breed [llm-agents llm-agent]
-breed [food-sources food-source]
-
-llm-agents-own [
- input ;; observation vector
- rule ;; current rule (llm-generated)
- energy ;; current score
- lifetime ;; age of the agent (in generations)
- food-collected ;; total food agent gathered
- parent-id ;; who number of parent
- parent-rule ;; parent rule
- pseudocode ;; descriptive text rule
- parent-pseudocode ;; pseudocode associated with the parent
-]
-
-;;; Setup Procedures
-
-to setup-params
- if use-config-file? [
- carefully [
- run word "setup-params-" config-file
- ] [
- user-message word config-file " is not a valid config file."
- ]
- ]
-end
-
-to-report get-additional-params
- report (list
- list "num-food-sources" num-food-sources
- list "init-rule" init-rule
- list "init-pseudocode" init-pseudocode
- )
-end
-
-to setup-llm-agents
- create-llm-agents num-llm-agents [
- set color red
- setxy random-xcor random-ycor
- set rule init-rule
- set parent-id "na"
- set parent-rule "na"
- set pseudocode init-pseudocode
- set parent-pseudocode "na"
- init-agent-params ;; Init with zero energy
- ]
-end
-
-to init-agent-params
- set energy 0
- set food-collected 0
- set lifetime 0
-end
-
-to spawn-food [num]
- create-food-sources num [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
-end
-
-to setup
- clear-all
-
- py:setup py:python
- py:run "import os"
- py:run "import sys"
- py:run "from pathlib import Path"
- py:run "sys.path.append(os.path.dirname(os.path.abspath('..')))"
- py:run "from src.mutation.mutate_code import mutate_code"
-
- set init-rule "lt random 20 rt random 20 fd 1"
- set init-pseudocode "Take left turn randomly within 0-20 degrees, then take right turn randomly within 0-20 degrees and move forward 1"
-
- set generation-stats []
- set error-log []
- set best-rule-fitness 0
-
- spawn-food num-food-sources
- setup-llm-agents
- setup-params
- if logging? [ setup-logger get-additional-params ]
- write-prompt-config prompt-type prompt-name
- reset-ticks
-end
-
-;;; Go Procedures
-
-to go
- do-plotting
- ask llm-agents [
- set lifetime lifetime + 1
- set input get-observation
- run-rule
- eat-food
- ]
- evolve-agents
- replenish-food
- tick
-end
-
-to run-rule
- carefully [
- run rule
- ] [
- let error-info (word
- "ERROR WHILE RUNNING RULE: " rule
- " | Agent: " who
- " | Tick: " ticks
- " | Fitness: " fitness
- " | Lifetime: " lifetime
- " | Food Collected: " food-collected
- " | Input: " input
- " | Error: " error-message
- )
- if ticks mod ticks-per-generation = 1 [
- if verbose? [ print error-info ]
- set error-log lput error-info error-log
- ]
- ]
-end
-
-to evolve-agents
- if ticks >= 1 and ticks mod ticks-per-generation = 0 [
- print word "\nGeneration: " generation
-
- let parents select-agents
- let kill-num length parents
-
- let kill-dict agent-dict min-n-of kill-num llm-agents [fitness]
- let best-dict agent-dict turtle-set parents
- let new-agent-ids []
-
- foreach parents [ parent ->
- ask parent [
- let my-parent-id who
- let my-rule rule
- let my-pseudocode pseudocode
- hatch 1 [
- set parent-id my-parent-id
- set parent-rule my-rule
- set parent-pseudocode my-pseudocode
- set rule mutate-rule
- init-agent-params
- set new-agent-ids lput who new-agent-ids
- ]
- ]
- ]
-
- ask min-n-of kill-num llm-agents with [not member? who new-agent-ids] [fitness] [ die ]
-
- let new-dict agent-dict llm-agents with [member? who new-agent-ids]
- update-generation-stats
- log-metrics (list best-dict new-dict kill-dict)
- set error-log []
-
- ask llm-agents [
- set food-collected 0
- set energy 0
- ]
- ]
-end
-
-to eat-food
- if any? food-sources-here [
- ask one-of food-sources-here [
- die
- ]
- set energy energy + 1
- set food-collected food-collected + 1
- ]
-end
-
-to replenish-food
- if count food-sources < num-food-sources [
- spawn-food (num-food-sources - count food-sources)
- ]
-end
-
-;;; Helpers and Observable Reporters
-
-to-report fitness
- report energy
-end
-
-to-report mean-fitness
- report mean [fitness] of llm-agents
-end
-
-to-report get-observation
- let dist 7
- let angle 20
- let obs []
- ;; obs order is [left-cone right-cone center-cone]
- foreach [-20 40 -20] [a ->
- rt a
- set obs lput (get-in-cone dist angle) obs
- ]
- report obs
-end
-
-to-report get-in-cone [dist angle]
- let val 0
- let cone other food-sources in-cone dist angle
- let f min-one-of cone with [is-food-source? self] [distance myself]
- if f != nobody [
- set val distance f
- ]
- report val
-end
-
-to-report get-generation-metrics
- let keys ["generation" "best rule" "mean fitness" "best fitness" "mean food" "error log"]
- let values ifelse-value any? llm-agents [
- (list
- generation
- best-rule
- mean-fitness
- max [fitness] of llm-agents
- mean [food-collected] of llm-agents
- error-log)
- ] [
- (list generation "na" 0 0 0 [])
- ]
- report fp:zip keys values
-end
-
-;;; Plotting
-
-to do-plotting
- if ticks mod ticks-per-generation = 0 [
- set-current-plot "Mean Energy of Agents"
- set-current-plot-pen "Mean Energy"
- plotxy generation mean-fitness
- set-current-plot-pen "Max Energy"
- plotxy generation max [energy] of llm-agents
- ]
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-210
-10
-647
-448
--1
--1
-13.0
-1
-10
-1
-1
-1
-0
-1
-1
-1
--16
-16
--16
-16
-1
-1
-1
-ticks
-30.0
-
-BUTTON
-20
-190
-90
-223
-NIL
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-100
-190
-170
-223
-NIL
-go
-T
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-SLIDER
-20
-20
-195
-53
-num-llm-agents
-num-llm-agents
-0
-25
-10.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-60
-195
-93
-num-food-sources
-num-food-sources
-0
-100
-30.0
-1
-1
-NIL
-HORIZONTAL
-
-SWITCH
-20
-240
-195
-273
-llm-mutation?
-llm-mutation?
-0
-1
--1000
-
-PLOT
-680
-60
-1090
-350
-Mean Energy of Agents
-generation
-energy
-0.0
-5.0
-0.0
-10.0
-true
-true
-"" ""
-PENS
-"Mean Energy" 1.0 0 -817084 true "" ""
-"Max Energy" 1.0 0 -13345367 true "" ""
-
-SLIDER
-20
-100
-195
-133
-ticks-per-generation
-ticks-per-generation
-1
-2000
-500.0
-1
-1
-NIL
-HORIZONTAL
-
-MONITOR
-680
-10
-757
-55
-NIL
-generation
-17
-1
-11
-
-CHOOSER
-20
-320
-195
-365
-llm-type
-llm-type
-"groq" "claude" "deepseek" "gpt-4o"
-0
-
-SWITCH
-20
-140
-195
-173
-logging?
-logging?
-0
-1
--1000
-
-SWITCH
-20
-280
-195
-313
-text-based-evolution
-text-based-evolution
-1
-1
--1000
-
-INPUTBOX
-20
-370
-195
-430
-experiment-name
-texttest
-1
-0
-String
-
-CHOOSER
-20
-470
-195
-515
-selection
-selection
-"tournament" "fitness-prop"
-0
-
-SLIDER
-20
-520
-195
-553
-num-parents
-num-parents
-0
-10
-1.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-560
-195
-593
-tournament-size
-tournament-size
-0
-50
-8.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-600
-195
-633
-selection-pressure
-selection-pressure
-0
-1
-0.8
-0.01
-1
-NIL
-HORIZONTAL
-
-SWITCH
-210
-470
-385
-503
-use-config-file?
-use-config-file?
-1
-1
--1000
-
-INPUTBOX
-210
-510
-385
-570
-config-file
-default
-1
-0
-String
-
-SWITCH
-400
-470
-575
-503
-verbose?
-verbose?
-1
-1
--1000
-
-INPUTBOX
-400
-510
-629
-570
-prompt-type
-collection_simple
-1
-0
-String
-
-INPUTBOX
-635
-510
-864
-570
-prompt-name
-one_shot_code_wcomments
-1
-0
-String
-
-CHOOSER
-635
-575
-862
-620
-prompt-name
-prompt-name
-"zero_shot_code" "one_shot_code" "two_shot_code" "zero_shot_code_wcomments" "one_shot_code_wcomments" "two_shot_code_wcomments"
-4
-
-@#$#@#$#@
-## WHAT IS IT?
-
-(a general understanding of what the model is trying to show or explain)
-
-## HOW IT WORKS
-
-(what rules the agents use to create the overall behavior of the model)
-
-## HOW TO USE IT
-
-(how to use the model, including a description of each of the items in the Interface tab)
-
-## THINGS TO NOTICE
-
-(suggested things for the user to notice while running the model)
-
-## THINGS TO TRY
-
-(suggested things for the user to try to do (move sliders, switches, etc.) with the model)
-
-## EXTENDING THE MODEL
-
-(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)
-
-## NETLOGO FEATURES
-
-(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)
-
-## RELATED MODELS
-
-(models in the NetLogo Models Library and elsewhere which are of related interest)
-
-## CREDITS AND REFERENCES
-
-(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-airplane
-true
-0
-Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15
-
-arrow
-true
-0
-Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150
-
-box
-false
-0
-Polygon -7500403 true true 150 285 285 225 285 75 150 135
-Polygon -7500403 true true 150 135 15 75 150 15 285 75
-Polygon -7500403 true true 15 75 15 225 150 285 150 135
-Line -16777216 false 150 285 150 135
-Line -16777216 false 150 135 15 75
-Line -16777216 false 150 135 285 75
-
-bug
-true
-0
-Circle -7500403 true true 96 182 108
-Circle -7500403 true true 110 127 80
-Circle -7500403 true true 110 75 80
-Line -7500403 true 150 100 80 30
-Line -7500403 true 150 100 220 30
-
-butterfly
-true
-0
-Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
-Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
-Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
-Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
-Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
-Circle -16777216 true false 135 90 30
-Line -16777216 false 150 105 195 60
-Line -16777216 false 150 105 105 60
-
-car
-false
-0
-Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
-Circle -16777216 true false 180 180 90
-Circle -16777216 true false 30 180 90
-Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
-Circle -7500403 true true 47 195 58
-Circle -7500403 true true 195 195 58
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-
-circle 2
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-
-cow
-false
-0
-Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
-Polygon -7500403 true true 73 210 86 251 62 249 48 208
-Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123
-
-cylinder
-false
-0
-Circle -7500403 true true 0 0 300
-
-dot
-false
-0
-Circle -7500403 true true 90 90 120
-
-face happy
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240
-
-face neutral
-false
-0
-Circle -7500403 true true 8 7 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Rectangle -16777216 true false 60 195 240 225
-
-face sad
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183
-
-fish
-false
-0
-Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
-Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
-Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
-Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
-Circle -16777216 true false 215 106 30
-
-flag
-false
-0
-Rectangle -7500403 true true 60 15 75 300
-Polygon -7500403 true true 90 150 270 90 90 30
-Line -7500403 true 75 135 90 135
-Line -7500403 true 75 45 90 45
-
-flower
-false
-0
-Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
-Circle -7500403 true true 85 132 38
-Circle -7500403 true true 130 147 38
-Circle -7500403 true true 192 85 38
-Circle -7500403 true true 85 40 38
-Circle -7500403 true true 177 40 38
-Circle -7500403 true true 177 132 38
-Circle -7500403 true true 70 85 38
-Circle -7500403 true true 130 25 38
-Circle -7500403 true true 96 51 108
-Circle -16777216 true false 113 68 74
-Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
-Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240
-
-house
-false
-0
-Rectangle -7500403 true true 45 120 255 285
-Rectangle -16777216 true false 120 210 180 285
-Polygon -7500403 true true 15 120 150 15 285 120
-Line -16777216 false 30 120 270 120
-
-leaf
-false
-0
-Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
-Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195
-
-line
-true
-0
-Line -7500403 true 150 0 150 300
-
-line half
-true
-0
-Line -7500403 true 150 0 150 150
-
-pentagon
-false
-0
-Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120
-
-person
-false
-0
-Circle -7500403 true true 110 5 80
-Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
-Rectangle -7500403 true true 127 79 172 94
-Polygon -7500403 true true 195 90 240 150 225 180 165 105
-Polygon -7500403 true true 105 90 60 150 75 180 135 105
-
-plant
-false
-0
-Rectangle -7500403 true true 135 90 165 300
-Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
-Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
-Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
-Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
-Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
-Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
-Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90
-
-sheep
-false
-15
-Circle -1 true true 203 65 88
-Circle -1 true true 70 65 162
-Circle -1 true true 150 105 120
-Polygon -7500403 true false 218 120 240 165 255 165 278 120
-Circle -7500403 true false 214 72 67
-Rectangle -1 true true 164 223 179 298
-Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
-Circle -1 true true 3 83 150
-Rectangle -1 true true 65 221 80 296
-Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
-Polygon -7500403 true false 276 85 285 105 302 99 294 83
-Polygon -7500403 true false 219 85 210 105 193 99 201 83
-
-square
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-
-square 2
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-Rectangle -16777216 true false 60 60 240 240
-
-star
-false
-0
-Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108
-
-target
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-Circle -7500403 true true 60 60 180
-Circle -16777216 true false 90 90 120
-Circle -7500403 true true 120 120 60
-
-tree
-false
-0
-Circle -7500403 true true 118 3 94
-Rectangle -6459832 true false 120 195 180 300
-Circle -7500403 true true 65 21 108
-Circle -7500403 true true 116 41 127
-Circle -7500403 true true 45 90 120
-Circle -7500403 true true 104 74 152
-
-triangle
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-
-triangle 2
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-Polygon -16777216 true false 151 99 225 223 75 224
-
-truck
-false
-0
-Rectangle -7500403 true true 4 45 195 187
-Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
-Rectangle -1 true false 195 60 195 105
-Polygon -16777216 true false 238 112 252 141 219 141 218 112
-Circle -16777216 true false 234 174 42
-Rectangle -7500403 true true 181 185 214 194
-Circle -16777216 true false 144 174 42
-Circle -16777216 true false 24 174 42
-Circle -7500403 false true 24 174 42
-Circle -7500403 false true 144 174 42
-Circle -7500403 false true 234 174 42
-
-turtle
-true
-0
-Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
-Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
-Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
-Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
-Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
-Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99
-
-wheel
-false
-0
-Circle -7500403 true true 3 3 294
-Circle -16777216 true false 30 30 240
-Line -7500403 true 150 285 150 15
-Line -7500403 true 15 150 285 150
-Circle -7500403 true true 120 120 60
-Line -7500403 true 216 40 79 269
-Line -7500403 true 40 84 269 221
-Line -7500403 true 40 216 269 79
-Line -7500403 true 84 40 221 269
-
-wolf
-false
-0
-Polygon -16777216 true false 253 133 245 131 245 133
-Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
-Polygon -7500403 true true -1 195 14 180 36 166 40 153 53 140 82 131 134 133 159 126 188 115 227 108 236 102 238 98 268 86 269 92 281 87 269 103 269 113
-
-x
-false
-0
-Polygon -7500403 true true 270 75 225 30 30 225 75 270
-Polygon -7500403 true true 30 75 75 30 270 225 225 270
-@#$#@#$#@
-NetLogo 6.4.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
- ticks mod ticks-per-generation = 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/simple-collection-env.nlogox b/demos/old-version-files/simple-collection-env.nlogox
deleted file mode 100644
index 625758d..0000000
--- a/demos/old-version-files/simple-collection-env.nlogox
+++ /dev/null
@@ -1,1630 +0,0 @@
-
-
- 0 and ticks mod 100 = 0 [
- evolve
- ]
-
- ; Replenish food
- if count foods < 20 [
- create-foods (20 - count foods) [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
- ]
-
- tick
-end
-
-to eat-food
- if any? foods-here [
- ask one-of foods-here [ die ]
- set energy energy + 1
- ]
-end
-
-to evolve
- set generation generation + 1
- print (word "Generation " generation)
-
- ; Find best agent
- let best-agent max-one-of agents [energy]
- if best-agent != nobody [
- ask best-agent [
- if energy > best-fitness [
- set best-fitness energy
- set best-rule rule
- print (word "New best: " rule " fitness: " energy)
- ]
- ]
- ]
-
- ; Kill worst agents and replace with mutated versions
- let worst-agents min-n-of 3 agents [energy]
- ask worst-agents [
- set rule mutate-rule [rule] of best-agent
- set energy 0
- ]
-
- ; Reset all energy
- ask agents [ set energy 0 ]
-end
-
-to-report mutate-rule [parent-rule]
- let prompt (word "Improve this NetLogo rule for finding food: " parent-rule
- " Return only NetLogo code, one line, using: fd, bk, rt, lt, random")
-
- let new-rule parent-rule
- carefully [
- set new-rule llm:chat prompt
- ] [
- ; Fallback if LLM fails
- set new-rule one-of ["fd 1 rt random 60" "fd 2 lt random 45" "fd 1"]
- ]
-
- report new-rule
-end]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- generation
-
-
-
-
-
-
-
-
- texttest
-
-
-
-
-
-
-
-
- default
-
- collection_simple
- one_shot_code_wcomments
-
-
-
-
-
-
-
-
-
- ## WHAT IS IT?
-
-(a general understanding of what the model is trying to show or explain)
-
-## HOW IT WORKS
-
-(what rules the agents use to create the overall behavior of the model)
-
-## HOW TO USE IT
-
-(how to use the model, including a description of each of the items in the Interface tab)
-
-## THINGS TO NOTICE
-
-(suggested things for the user to notice while running the model)
-
-## THINGS TO TRY
-
-(suggested things for the user to try to do (move sliders, switches, etc.) with the model)
-
-## EXTENDING THE MODEL
-
-(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)
-
-## NETLOGO FEATURES
-
-(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)
-
-## RELATED MODELS
-
-(models in the NetLogo Models Library and elsewhere which are of related interest)
-
-## CREDITS AND REFERENCES
-
-(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup repeat 75 [ go ]
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setup
- go
- ticks mod ticks-per-generation = 0
-
- generation
- mean-fitness
- max [fitness] of llm-agents
- best-rule-fitness
- best-rule
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demos/old-version-files/simple-llm-demo.nlogo b/demos/old-version-files/simple-llm-demo.nlogo
deleted file mode 100644
index d1336c9..0000000
--- a/demos/old-version-files/simple-llm-demo.nlogo
+++ /dev/null
@@ -1,516 +0,0 @@
-extensions [llm]
-
-globals [
- colors
-]
-
-turtles-own [
- name
- favorite-color
- last-message
-]
-
-to setup
- clear-all
-
- ; Load LLM configuration
- llm:load-config "demos/config"
-
- set-default-shape turtles "person"
-
- let names ["Alice" "Ben" "Cindy" "David" "Emily" "Frank"]
- set colors ["red" "blue" "green" "yellow" "purple" "orange"]
-
- create-turtles num-agents [
- setxy random-xcor random-ycor
- set size 2
- set name item who names
- set favorite-color one-of colors
- set color runresult favorite-color
- set last-message ""
-
- ; Set up personality for each agent
- llm:set-history (list
- (list "system" (word
- "You are " name " and your favorite color is " favorite-color ". "
- "You are friendly and like to chat with others. "
- "Keep your responses short (1-2 sentences). "
- "Try to learn about other agents' favorite colors."))
- )
- ]
-
- ask turtles [
- set label (word name ": " favorite-color)
- ]
-
- reset-ticks
-end
-
-to go
- ask turtles [
- ; Simple conversation with LLM
- let response llm:chat "What would you like to say to introduce yourself?"
- set last-message response
- set label (word name ": " first 30 response)
- ]
-
- tick
-end
-
-to test-llm
- ; Simple test function
- let response llm:chat "Say hello and introduce yourself briefly."
- print response
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-210
-10
-647
-448
--1
--1
-13.0
-1
-10
-1
-1
-1
-0
-1
-1
-1
--16
-16
--16
-16
-0
-0
-1
-ticks
-30.0
-
-BUTTON
-15
-45
-88
-78
-NIL
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-110
-45
-175
-78
-NIL
-go
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-SLIDER
-15
-10
-187
-43
-num-agents
-num-agents
-1
-6
-4.0
-1
-1
-NIL
-HORIZONTAL
-
-BUTTON
-15
-100
-100
-133
-Test LLM
-test-llm
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-TEXTBOX
-15
-150
-200
-220
-Simple LLM Extension Demo:\n1. Click SETUP to create agents\n2. Click GO to have them chat\n3. Use Test LLM to verify connection
-11
-0.0
-1
-
-@#$#@#$#@
-## WHAT IS IT?
-
-A simple demo of the NetLogo LLM Extension. Agents use AI to generate conversations and introduce themselves.
-
-## HOW TO USE IT
-
-1. Make sure demos/config.txt has your LLM provider set up
-2. Click SETUP to create agents with names and colors
-3. Click GO to have agents generate introductions using LLM
-4. Use "Test LLM" to verify the extension is working
-
-## THINGS TO NOTICE
-
-- Each agent gets a personality and favorite color
-- Agents use the LLM extension to generate natural responses
-- Responses are displayed as agent labels
-
-## EXTENDING THE MODEL
-
-- Add agent interactions and conversations
-- Implement learning and memory systems
-- Create more complex social behaviors
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-airplane
-true
-0
-Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15
-
-arrow
-true
-0
-Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150
-
-box
-false
-0
-Polygon -7500403 true true 150 285 285 225 285 75 150 135
-Polygon -7500403 true true 150 135 15 75 150 15 285 75
-Polygon -7500403 true true 15 75 15 225 150 285 150 135
-Line -16777216 false 150 285 150 135
-Line -16777216 false 150 135 15 75
-Line -16777216 false 150 135 285 75
-
-bug
-true
-0
-Circle -7500403 true true 96 182 108
-Circle -7500403 true true 110 127 80
-Circle -7500403 true true 110 75 80
-Line -7500403 true 150 100 80 30
-Line -7500403 true 150 100 220 30
-
-butterfly
-true
-0
-Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
-Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
-Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
-Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
-Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
-Circle -16777216 true false 135 90 30
-Line -16777216 false 150 105 195 60
-Line -16777216 false 150 105 105 60
-
-car
-false
-0
-Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
-Circle -16777216 true false 180 180 90
-Circle -16777216 true false 30 180 90
-Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
-Circle -7500403 true true 47 195 58
-Circle -7500403 true true 195 195 58
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-
-circle 2
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-
-cow
-false
-0
-Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
-Polygon -7500403 true true 73 210 86 251 62 249 48 208
-Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123
-
-cylinder
-false
-0
-Circle -7500403 true true 0 0 300
-
-dot
-false
-0
-Circle -7500403 true true 90 90 120
-
-face happy
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240
-
-face neutral
-false
-0
-Circle -7500403 true true 8 7 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Rectangle -16777216 true false 60 195 240 225
-
-face sad
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183
-
-fish
-false
-0
-Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
-Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
-Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
-Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
-Circle -16777216 true false 215 106 30
-
-flag
-false
-0
-Rectangle -7500403 true true 60 15 75 300
-Polygon -7500403 true true 90 150 270 90 90 30
-Line -7500403 true 75 135 90 135
-Line -7500403 true 75 45 90 45
-
-flower
-false
-0
-Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
-Circle -7500403 true true 85 132 38
-Circle -7500403 true true 130 147 38
-Circle -7500403 true true 192 85 38
-Circle -7500403 true true 85 40 38
-Circle -7500403 true true 177 40 38
-Circle -7500403 true true 177 132 38
-Circle -7500403 true true 70 85 38
-Circle -7500403 true true 130 25 38
-Circle -7500403 true true 96 51 108
-Circle -16777216 true false 113 68 74
-Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
-Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240
-
-house
-false
-0
-Rectangle -7500403 true true 45 120 255 285
-Rectangle -16777216 true false 120 210 180 285
-Polygon -7500403 true true 15 120 150 15 285 120
-Line -16777216 false 30 120 270 120
-
-leaf
-false
-0
-Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
-Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195
-
-line
-true
-0
-Line -7500403 true 150 0 150 300
-
-line half
-true
-0
-Line -7500403 true 150 0 150 150
-
-pentagon
-false
-0
-Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120
-
-person
-false
-0
-Circle -7500403 true true 110 5 80
-Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
-Rectangle -7500403 true true 127 79 172 94
-Polygon -7500403 true true 195 90 240 150 225 180 165 105
-Polygon -7500403 true true 105 90 60 150 75 180 135 105
-
-plant
-false
-0
-Rectangle -7500403 true true 135 90 165 300
-Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
-Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
-Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
-Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
-Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
-Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
-Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90
-
-sheep
-false
-15
-Circle -1 true true 203 65 88
-Circle -1 true true 70 65 162
-Circle -1 true true 150 105 120
-Polygon -7500403 true false 218 120 240 165 255 165 278 120
-Circle -7500403 true false 214 72 67
-Rectangle -1 true true 164 223 179 298
-Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
-Circle -1 true true 3 83 150
-Rectangle -1 true true 65 221 80 296
-Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
-Polygon -7500403 true false 276 85 285 105 302 99 294 83
-Polygon -7500403 true false 219 85 210 105 193 99 201 83
-
-square
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-
-square 2
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-Rectangle -16777216 true false 60 60 240 240
-
-star
-false
-0
-Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108
-
-target
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-Circle -7500403 true true 60 60 180
-Circle -16777216 true false 90 90 120
-Circle -7500403 true true 120 120 60
-
-tree
-false
-0
-Circle -7500403 true true 118 3 94
-Rectangle -6459832 true false 120 195 180 300
-Circle -7500403 true true 65 21 108
-Circle -7500403 true true 116 41 127
-Circle -7500403 true true 45 90 120
-Circle -7500403 true true 104 74 152
-
-triangle
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-
-triangle 2
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-Polygon -16777216 true false 151 99 225 223 75 224
-
-truck
-false
-0
-Rectangle -7500403 true true 4 45 195 187
-Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
-Rectangle -1 true false 195 60 195 105
-Polygon -16777216 true false 238 112 252 141 219 141 218 112
-Circle -16777216 true false 234 174 42
-Rectangle -7500403 true true 181 185 214 194
-Circle -16777216 true false 144 174 42
-Circle -16777216 true false 24 174 42
-Circle -7500403 false true 24 174 42
-Circle -7500403 false true 144 174 42
-Circle -7500403 false true 234 174 42
-
-turtle
-true
-0
-Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
-Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
-Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
-Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
-Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
-Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99
-
-wheel
-false
-0
-Circle -7500403 true true 3 3 294
-Circle -16777216 true false 30 30 240
-Line -7500403 true 150 285 150 15
-Line -7500403 true 15 150 285 150
-Circle -7500403 true true 120 120 60
-Line -7500403 true 216 40 79 269
-Line -7500403 true 40 84 269 221
-Line -7500403 true 40 216 269 79
-Line -7500403 true 84 40 221 269
-
-wolf
-false
-0
-Polygon -16777216 true false 253 133 245 131 245 133
-Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
-Polygon -7500403 true true -1 195 14 180 36 166 40 153 53 140 82 131 134 133 159 126 188 115 227 108 236 102 238 98 268 86 269 92 281 87 269 103 269 113
-
-x
-false
-0
-Polygon -7500403 true true 270 75 225 30 30 225 75 270
-Polygon -7500403 true true 30 75 75 30 270 225 225 270
-@#$#@#$#@
-NetLogo 6.3.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/simple-llm-evolution.nlogo b/demos/old-version-files/simple-llm-evolution.nlogo
deleted file mode 100644
index a16ef30..0000000
--- a/demos/old-version-files/simple-llm-evolution.nlogo
+++ /dev/null
@@ -1,251 +0,0 @@
-extensions [ llm ]
-
-globals [
- generation
- best-fitness
-]
-
-breed [agents agent]
-breed [food-sources food-source]
-
-agents-own [
- rule
- energy
-]
-
-to setup
- clear-all
-
- ; Setup LLM
- llm:load-config "demos/config"
-
- set generation 0
- set best-fitness 0
-
- ; Create agents with initial rule
- create-agents 10 [
- set color red
- setxy random-xcor random-ycor
- set rule "fd 1 rt random 45"
- set energy 0
- ]
-
- ; Create food sources
- create-food-sources 20 [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
-
- reset-ticks
-end
-
-to go
- ; Agents act
- ask agents [
- carefully [
- run rule
- ] [
- ; If rule fails, do nothing
- ]
- collect-food
- ]
-
- ; Evolution every 100 ticks
- if ticks mod 100 = 0 and ticks > 0 [
- evolve
- ]
-
- ; Replenish food
- if count food-sources < 20 [
- create-food-sources (20 - count food-sources) [
- set shape "circle"
- set color green
- set size 0.5
- setxy random-xcor random-ycor
- ]
- ]
-
- tick
-end
-
-to collect-food
- if any? food-sources-here [
- ask one-of food-sources-here [ die ]
- set energy energy + 1
- ]
-end
-
-to evolve
- set generation generation + 1
- print (word "Generation: " generation)
-
- ; Find best performers
- let top-agents max-n-of 3 agents [energy]
-
- ; Update best fitness
- if any? top-agents [
- let current-best max [energy] of top-agents
- if current-best > best-fitness [
- set best-fitness current-best
- ]
- ]
-
- ; Evolve worst performers
- let worst-agents min-n-of 3 agents [energy]
-
- ask worst-agents [
- ; Get a good rule to mutate
- let parent-rule [rule] of one-of top-agents
- set rule mutate-with-llm parent-rule
- set energy 0
- ]
-
- ; Reset all energies
- ask agents [ set energy 0 ]
-end
-
-to-report mutate-with-llm [current-rule]
- let prompt (word
- "Improve this NetLogo movement rule for food collection: " current-rule
- " Make it better at finding food. Use only: fd, bk, rt, lt, random. Keep it simple, one line.")
-
- let new-rule ""
- carefully [
- set new-rule llm:chat prompt
- ; Clean up response
- if length new-rule > 50 [
- set new-rule current-rule
- ]
- ] [
- ; Fallback if LLM fails
- set new-rule (word "fd " (1 + random 2) " rt random " (30 + random 60))
- ]
-
- report new-rule
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-210
-10
-647
-448
--1
--1
-13.0
-1
-10
-1
-1
-1
-0
-1
-1
-1
--16
-16
--16
-16
-1
-1
-1
-ticks
-30.0
-
-BUTTON
-30
-30
-100
-63
-setup
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-110
-30
-180
-63
-go
-go
-T
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-MONITOR
-30
-80
-120
-125
-Generation
-generation
-0
-1
-11
-
-MONITOR
-130
-80
-220
-125
-Best Fitness
-best-fitness
-0
-1
-11
-
-@#$#@#$#@
-## Simple LLM Code Evolution
-
-Red agents evolve movement rules using an LLM to collect green food.
-
-1. Click SETUP
-2. Click GO
-3. Watch agents evolve better food-finding rules
-
-Every 100 ticks, the worst agents get new rules evolved from the best agents using the LLM.
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-@#$#@#$#@
-NetLogo 6.4.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/smart-agents-evolution.nlogox b/demos/old-version-files/smart-agents-evolution.nlogox
deleted file mode 100644
index 6a319be..0000000
--- a/demos/old-version-files/smart-agents-evolution.nlogox
+++ /dev/null
@@ -1,1108 +0,0 @@
-extensions [llm]
-
-globals [
- generation ; current generation counter
- evolution-log ; list of evolution events for display
- total-evolutions ; count of total rule changes
- best-rule ; current best performing rule
- best-energy ; energy of best performing agent
- unique-rules ; list of all current unique rules
- evolution-flash-agents ; agents that just evolved (for visual effect)
-]
-
-breed [smart-agents smart-agent]
-breed [food-sources food-source]
-
-smart-agents-own [
- movement-rule ; NetLogo code string for movement
- energy ; food collected
- evolution-count ; how many times this agent evolved
- flash-timer ; for visual evolution effect
- rule-history ; string of previous rules for display
-]
-
-;;; Setup Procedures
-
-to setup
- clear-all
-
- ; Initialize globals
- set generation 0
- set evolution-log []
- set total-evolutions 0
- set best-rule "fd 1"
- set best-energy 0
- set unique-rules []
- set evolution-flash-agents []
-
- ; Create food scattered around
- ask n-of num-food patches [
- sprout-food-sources 1 [
- set color green
- set shape "circle"
- set size 0.5
- ]
- ]
-
- ; Create smart agents with simple starting rule
- create-smart-agents num-agents [
- set movement-rule "fd 1"
- set energy 0
- set evolution-count 0
- set flash-timer 0
- set rule-history ""
- set color red
- set size 1
- setxy random-xcor random-ycor
- set label movement-rule
- ]
-
- ; Update displays
- update-best-rule
- update-unique-rules
-
- reset-ticks
-end
-
-;;; Main Loop
-
-to go
- ; Move agents according to their rules
- ask smart-agents [
- move-with-rule
- collect-food
- update-visual-effects
- ]
-
- ; Evolution logic
- if ticks > 0 and ticks mod evolution-interval = 0 and not pause-evolution? [
- evolve-random-agent
- set generation generation + 1
- ]
-
- ; Maintenance
- replenish-food
- update-displays
-
- tick
-end
-
-;;; Agent Behavior
-
-to move-with-rule
- carefully [
- run movement-rule
- ] [
- ; If rule fails, use simple fallback
- fd 1
- ]
-end
-
-to collect-food
- if any? food-sources-here [
- ask one-of food-sources-here [ die ]
- set energy energy + 1
- set size 1 + (energy * 0.1) ; Visual size reflects energy
-
- ; Mark patch with faint green (food trail)
- ask patch-here [ set pcolor green - 3 ]
- ]
-end
-
-to update-visual-effects
- ; Handle evolution flash effect
- if flash-timer > 0 [
- set flash-timer flash-timer - 1
- if flash-timer <= 0 [
- set color red
- ]
- ]
-
- ; Update label with current rule
- if show-rules? [
- set label movement-rule
- ]
-end
-
-;;; Evolution System
-
-to evolve-random-agent
- if count smart-agents = 0 [ stop ]
-
- let evolving-agent one-of smart-agents
-
- ask evolving-agent [
- let old-rule movement-rule
- let old-energy energy
-
- ; Track rule in conversation history
- llm:chat (word "RULE_VERSION: " movement-rule " (energy: " energy ")")
-
- ; Get rule evolution history
- let rule-history-text get-rule-evolution-history
-
- ; Build environment info
- let env-info (word "Food nearby: " count food-sources in-radius 5
- " | Position: (" precision xcor 1 ", " precision ycor 1 ")")
-
- ; Use LLM template to evolve rule
- carefully [
- let new-rule llm:chat-with-template "demos/movement-evolution.yaml" (list
- ["current_rule" movement-rule]
- ["rule_history" rule-history-text]
- ["energy_collected" energy]
- ["environment_info" env-info]
- ["goal" "collect food more efficiently than current strategy"]
- )
-
- ; Clean the rule and apply it
- let cleaned-rule clean-netlogo-rule new-rule
- if cleaned-rule != "" [
- set movement-rule cleaned-rule
- set evolution-count evolution-count + 1
- set rule-history (word rule-history old-rule " โ ")
-
- ; Visual evolution effect
- set color yellow
- set flash-timer 20
-
- ; Log evolution event
- let evolution-event (word "Gen " generation ": Agent " who
- " evolved from '" old-rule "' to '" movement-rule "'")
- set evolution-log lput evolution-event evolution-log
- if length evolution-log > 10 [
- set evolution-log but-first evolution-log
- ]
-
- set total-evolutions total-evolutions + 1
-
- print evolution-event
- ]
- ] [
- ; If LLM call fails, make a simple random mutation
- set movement-rule mutate-rule-randomly movement-rule
- print (word "LLM failed, using random mutation for agent " who)
- ]
- ]
-
- update-displays
-end
-
-to-report get-rule-evolution-history
- let history llm:history
- let rule-versions []
- foreach history [ msg ->
- let role item 0 msg
- let content item 1 msg
- if role = "user" and (substring content 0 13) = "RULE_VERSION:" [
- set rule-versions lput (substring content 13 (length content)) rule-versions
- ]
- ]
-
- ifelse length rule-versions > 0 [
- report (reduce [(word ?1 "\n" ?2)] rule-versions)
- ] [
- report "No previous versions"
- ]
-end
-
-to-report clean-netlogo-rule [raw-rule]
- let cleaned raw-rule
-
- ; Remove common LLM response artifacts
- if position ":" cleaned != false [
- let colon-pos position ":" cleaned
- if colon-pos < 20 [ ; If colon near start, take text after it
- set cleaned substring cleaned (colon-pos + 1) (length cleaned)
- ]
- ]
-
- ; Remove quotes
- set cleaned remove "\"" cleaned
- set cleaned remove "'" cleaned
-
- ; Trim whitespace
- while [length cleaned > 0 and first cleaned = " "] [
- set cleaned substring cleaned 1 (length cleaned)
- ]
- while [length cleaned > 0 and last cleaned = " "] [
- set cleaned substring cleaned 0 (length cleaned - 1)
- ]
-
- ; Validate it contains only allowed commands
- if validate-rule cleaned [
- report cleaned
- ]
- report ""
-end
-
-to-report validate-rule [rule-string]
- ; Simple validation - check if rule contains only allowed commands
- let allowed-commands (list "fd" "bk" "lt" "rt" "random")
- let words-in-rule []
-
- ; Split rule into words (simplified)
- let current-word ""
- let i 0
- while [i < length rule-string] [
- let char substring rule-string i (i + 1)
- if char = " " [
- if current-word != "" [
- set words-in-rule lput current-word words-in-rule
- set current-word ""
- ]
- ] [
- set current-word (word current-word char)
- ]
- set i i + 1
- ]
- if current-word != "" [
- set words-in-rule lput current-word words-in-rule
- ]
-
- ; Check each word is either an allowed command or a number
- foreach words-in-rule [ word-item ->
- let is-command member? word-item allowed-commands
- let is-number false
- carefully [
- let num read-from-string word-item
- if is-number? num [ set is-number true ]
- ] [ ]
-
- if not (is-command or is-number) [
- report false
- ]
- ]
-
- report true
-end
-
-to-report mutate-rule-randomly [current-rule]
- ; Simple random mutations as fallback
- let mutations (list
- "fd 1"
- "lt 30 fd 1"
- "rt 45 fd 2"
- "fd random 3"
- "lt random 60 fd 1"
- "rt random 90 fd 2"
- )
- report one-of mutations
-end
-
-;;; Manual Evolution
-
-to evolve-now
- if count smart-agents > 0 [
- evolve-random-agent
- ]
-end
-
-;;; Food Management
-
-to replenish-food
- let food-needed num-food - count food-sources
- if food-needed > 0 [
- ask n-of (min list food-needed (count patches with [not any? food-sources-here]))
- patches with [not any? food-sources-here] [
- sprout-food-sources 1 [
- set color green
- set shape "circle"
- set size 0.5
- ]
- ]
- ]
-
- ; Fade food trails
- ask patches with [pcolor != black and pcolor != green] [
- set pcolor pcolor + 0.1
- if pcolor >= black [ set pcolor black ]
- ]
-end
-
-;;; Display Updates
-
-to update-displays
- update-best-rule
- update-unique-rules
-end
-
-to update-best-rule
- if any? smart-agents [
- let best-agent max-one-of smart-agents [energy]
- ask best-agent [
- set best-rule movement-rule
- set best-energy energy
- ]
- ]
-end
-
-to update-unique-rules
- set unique-rules []
- ask smart-agents [
- if not member? movement-rule unique-rules [
- set unique-rules lput movement-rule unique-rules
- ]
- ]
-end
-
-;;; Reporters
-
-to-report mean-energy
- ifelse any? smart-agents [
- report precision (mean [energy] of smart-agents) 1
- ] [
- report 0
- ]
-end
-
-to-report max-energy
- ifelse any? smart-agents [
- report max [energy] of smart-agents
- ] [
- report 0
- ]
-end
-
-to-report rule-diversity
- report length unique-rules
-end
-
-to-report evolution-events-text
- ifelse length evolution-log > 0 [
- report reduce [(word ?1 "\n" ?2)] evolution-log
- ] [
- report "No evolutions yet"
- ]
-end
-
-;;; Agent Interaction
-
-to inspect-agent
- if mouse-down? [
- let clicked-agent min-one-of smart-agents [distancexy mouse-xcor mouse-ycor]
- if clicked-agent != nobody and [distancexy mouse-xcor mouse-ycor] of clicked-agent < 2 [
- ask clicked-agent [
- let info (word "Agent " who ":\n"
- "Rule: " movement-rule "\n"
- "Energy: " energy "\n"
- "Evolutions: " evolution-count "\n"
- "History: " rule-history)
- user-message info
- ]
- wait 0.5 ; Prevent multiple clicks
- ]
- ]
-end
-@#$#@#$#@
-GRAPHICS-WINDOW
-210
-10
-647
-448
--1
--1
-13.0
-1
-10
-1
-1
-1
-0
-0
-0
-1
--16
-16
--16
-16
-1
-1
-1
-ticks
-30.0
-
-BUTTON
-20
-10
-83
-43
-setup
-setup
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-90
-10
-153
-43
-go
-go
-T
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-160
-10
-235
-43
-evolve now
-evolve-now
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-SLIDER
-20
-50
-192
-83
-num-agents
-num-agents
-3
-20
-10.0
-1
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-90
-192
-123
-num-food
-num-food
-20
-100
-50.0
-5
-1
-NIL
-HORIZONTAL
-
-SLIDER
-20
-130
-192
-163
-evolution-interval
-evolution-interval
-50
-500
-100.0
-50
-1
-ticks
-HORIZONTAL
-
-SWITCH
-20
-170
-192
-203
-show-rules?
-show-rules?
-0
-1
--1000
-
-SWITCH
-20
-210
-192
-243
-pause-evolution?
-pause-evolution?
-1
-1
--1000
-
-MONITOR
-20
-250
-100
-295
-generation
-generation
-0
-1
-11
-
-MONITOR
-110
-250
-190
-295
-best energy
-best-energy
-0
-1
-11
-
-MONITOR
-20
-300
-100
-345
-mean energy
-mean-energy
-1
-1
-11
-
-MONITOR
-110
-300
-190
-345
-rule diversity
-rule-diversity
-0
-1
-11
-
-MONITOR
-20
-350
-100
-395
-total evolutions
-total-evolutions
-0
-1
-11
-
-TEXTBOX
-20
-400
-190
-440
-Click agents to see details. Yellow flash = evolution!
-11
-0.0
-1
-
-PLOT
-660
-10
-1000
-200
-Agent Energy Over Time
-generation
-energy
-0.0
-10.0
-0.0
-20.0
-true
-true
-"" ""
-PENS
-"mean-energy" 1.0 0 -16777216 true "" "plot mean-energy"
-"max-energy" 1.0 0 -2674135 true "" "plot max-energy"
-
-PLOT
-660
-210
-1000
-400
-Rule Diversity Over Time
-generation
-unique rules
-0.0
-10.0
-0.0
-10.0
-true
-false
-"" ""
-PENS
-"diversity" 1.0 0 -13345367 true "" "plot rule-diversity"
-
-OUTPUT
-210
-460
-1000
-580
-12
-
-TEXTBOX
-210
-585
-1000
-625
-Evolution Log: Recent rule changes appear above. Watch agents flash yellow when they evolve!
-11
-0.0
-1
-
-BUTTON
-660
-410
-760
-443
-clear output
-clear-output
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-BUTTON
-770
-410
-900
-443
-show evolution log
-output-print evolution-events-text
-NIL
-1
-T
-OBSERVER
-NIL
-NIL
-NIL
-NIL
-1
-
-TEXTBOX
-660
-450
-1000
-480
-LLM Extension Demo: Smart Agents with Evolving Movement Rules
-14
-0.0
-1
-@#$#@#$#@
-## WHAT IS IT?
-
-This model demonstrates the LLM extension's template system by showing agents that evolve their movement rules using artificial intelligence. Each agent has a NetLogo code string that controls how it moves, and periodically agents use LLM reasoning to improve their movement strategies based on their performance history.
-
-## HOW IT WORKS
-
-**Agents:** Each smart-agent has a `movement-rule` (NetLogo code string) that it executes each tick to move around the world.
-
-**Food Collection:** Agents collect green food circles by moving over them, gaining energy and increasing in size.
-
-**Evolution:** Every `evolution-interval` ticks, a random agent uses the LLM extension's template system to evolve its movement rule. The agent:
-1. Tracks its rule history using conversation history
-2. Uses a YAML template (`movement-evolution.yaml`) with variables for current rule, history, energy, and environment
-3. Gets an improved movement rule from the LLM
-4. Adopts the new rule and flashes yellow
-
-**Visual Feedback:** Agents show their current rules as labels, flash yellow when evolving, grow with energy, and leave faint green trails where they collect food.
-
-## HOW TO USE IT
-
-1. **Setup:** Click `setup` to create agents and food
-2. **Run:** Click `go` to start the simulation
-3. **Configure:** Use sliders to adjust number of agents, food, and evolution frequency
-4. **Manual Evolution:** Click `evolve now` to trigger evolution immediately
-5. **Inspect:** Click on any agent to see its detailed history
-6. **Monitor:** Watch plots and monitors to track energy and rule diversity over time
-
-**Controls:**
-- `show-rules?`: Toggle display of movement rules on agents
-- `pause-evolution?`: Stop automatic evolution while keeping simulation running
-
-## THINGS TO NOTICE
-
-- **Evolution Events:** Agents flash bright yellow when they evolve new rules
-- **Performance Growth:** Successful agents collect more food and grow larger
-- **Rule Diversity:** Watch how many unique movement strategies emerge
-- **Visual Trails:** Green patches show where food was recently collected
-- **Rule Complexity:** Rules start simple ("fd 1") but can become sophisticated
-
-## THINGS TO TRY
-
-- **Different Evolution Speeds:** Try fast evolution (50 ticks) vs slow (500 ticks)
-- **Population Size:** Compare small groups (5 agents) vs large (20 agents)
-- **Food Density:** See how food scarcity affects rule evolution
-- **Manual Inspection:** Click agents to see their rule evolution history
-- **Pause and Observe:** Use `pause-evolution?` to study current strategies
-
-## EXTENDING THE MODEL
-
-- **New Templates:** Create specialized YAML templates for different goals
-- **Environmental Challenges:** Add obstacles or moving food
-- **Communication:** Let agents share successful strategies
-- **Multiple Objectives:** Balance food collection with other goals
-- **Rule Validation:** Add constraints to prevent invalid movements
-
-## LLM EXTENSION FEATURES
-
-This model showcases:
-- **Template System:** YAML-based structured prompting with variable substitution
-- **Conversation History:** Agents remember their rule evolution journey
-- **Error Handling:** Graceful fallbacks when LLM calls fail
-- **Visual Integration:** AI reasoning made visible through NetLogo graphics
-
-## TECHNICAL NOTES
-
-**Requirements:**
-- LLM extension installed
-- Valid LLM provider configured (OpenAI, Anthropic, etc.)
-- Internet connection for LLM API calls
-
-**Template File:** `demos/movement-evolution.yaml` defines the evolution prompts
-
-**Fallback Behavior:** If LLM calls fail, agents use simple random mutations
-
-## CREDITS AND REFERENCES
-
-Created to demonstrate the NetLogo LLM Extension's template capabilities.
-Extension available at: https://github.com/NetLogo/LLM-Extension
-@#$#@#$#@
-default
-true
-0
-Polygon -7500403 true true 150 5 40 250 150 205 260 250
-
-airplane
-true
-0
-Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15
-
-arrow
-true
-0
-Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150
-
-box
-false
-0
-Polygon -7500403 true true 150 285 285 225 285 75 150 135
-Polygon -7500403 true true 150 135 15 75 150 15 285 75
-Polygon -7500403 true true 15 75 15 225 150 285 150 135
-Line -16777216 false 150 285 150 135
-Line -16777216 false 150 135 15 75
-Line -16777216 false 150 135 285 75
-
-bug
-true
-0
-Circle -7500403 true true 96 182 108
-Circle -7500403 true true 110 127 80
-Circle -7500403 true true 110 75 80
-Line -7500403 true 150 100 80 30
-Line -7500403 true 150 100 220 30
-
-butterfly
-true
-0
-Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
-Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
-Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
-Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
-Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
-Circle -16777216 true false 135 90 30
-Line -16777216 false 150 105 195 60
-Line -16777216 false 150 105 105 60
-
-car
-false
-0
-Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
-Circle -16777216 true false 180 180 90
-Circle -16777216 true false 30 180 90
-Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
-Circle -7500403 true true 47 195 58
-Circle -7500403 true true 195 195 58
-
-circle
-false
-0
-Circle -7500403 true true 0 0 300
-
-circle 2
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-
-cow
-false
-0
-Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
-Polygon -7500403 true true 73 210 86 251 62 249 48 208
-Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123
-
-cylinder
-false
-0
-Circle -7500403 true true 0 0 300
-
-dot
-false
-0
-Circle -7500403 true true 90 90 120
-
-face happy
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240
-
-face neutral
-false
-0
-Circle -7500403 true true 8 7 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Rectangle -16777216 true false 60 195 240 225
-
-face sad
-false
-0
-Circle -7500403 true true 8 8 285
-Circle -16777216 true false 60 75 60
-Circle -16777216 true false 180 75 60
-Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183
-
-fish
-false
-0
-Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
-Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
-Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
-Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
-Circle -16777216 true false 215 106 30
-
-flag
-false
-0
-Rectangle -7500403 true true 60 15 75 300
-Polygon -7500403 true true 90 150 270 90 90 30
-Line -7500403 true 75 135 90 135
-Line -7500403 true 75 45 90 45
-
-flower
-false
-0
-Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
-Circle -7500403 true true 85 132 38
-Circle -7500403 true true 130 147 38
-Circle -7500403 true true 192 85 38
-Circle -7500403 true true 85 40 38
-Circle -7500403 true true 177 40 38
-Circle -7500403 true true 177 132 38
-Circle -7500403 true true 70 85 38
-Circle -7500403 true true 130 25 38
-Circle -7500403 true true 96 51 108
-Circle -16777216 true false 113 68 74
-Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
-Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240
-
-house
-false
-0
-Rectangle -7500403 true true 45 120 255 285
-Rectangle -16777216 true false 120 210 180 285
-Polygon -7500403 true true 15 120 150 15 285 120
-Line -16777216 false 30 120 270 120
-
-leaf
-false
-0
-Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
-Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195
-
-line
-true
-0
-Line -7500403 true 150 0 150 300
-
-line half
-true
-0
-Line -7500403 true 150 0 150 150
-
-pentagon
-false
-0
-Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120
-
-person
-false
-0
-Circle -7500403 true true 110 5 80
-Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
-Rectangle -7500403 true true 127 79 172 94
-Polygon -7500403 true true 195 90 240 150 225 180 165 105
-Polygon -7500403 true true 105 90 60 150 75 180 135 105
-
-plant
-false
-0
-Rectangle -7500403 true true 135 90 165 300
-Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
-Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
-Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
-Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
-Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
-Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
-Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90
-
-sheep
-false
-15
-Circle -1 true true 203 65 88
-Circle -1 true true 70 65 162
-Circle -1 true true 150 105 120
-Polygon -7500403 true false 218 120 240 165 255 165 278 120
-Circle -7500403 true false 214 72 67
-Rectangle -1 true true 164 223 179 298
-Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
-Circle -1 true true 3 83 150
-Rectangle -1 true true 65 221 80 296
-Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
-Polygon -7500403 true false 276 85 285 105 302 99 294 83
-Polygon -7500403 true false 219 85 210 105 193 99 201 83
-
-square
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-
-square 2
-false
-0
-Rectangle -7500403 true true 30 30 270 270
-Rectangle -16777216 true false 60 60 240 240
-
-star
-false
-0
-Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108
-
-target
-false
-0
-Circle -7500403 true true 0 0 300
-Circle -16777216 true false 30 30 240
-Circle -7500403 true true 60 60 180
-Circle -16777216 true false 90 90 120
-Circle -7500403 true true 120 120 60
-
-tree
-false
-0
-Circle -7500403 true true 118 3 94
-Rectangle -6459832 true false 120 195 180 300
-Circle -7500403 true true 65 21 108
-Circle -7500403 true true 116 41 127
-Circle -7500403 true true 45 90 120
-Circle -7500403 true true 104 74 152
-
-triangle
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-
-triangle 2
-false
-0
-Polygon -7500403 true true 150 30 15 255 285 255
-Polygon -16777216 true false 151 99 225 223 75 224
-
-truck
-false
-0
-Rectangle -7500403 true true 4 45 195 187
-Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
-Rectangle -1 true false 195 60 195 105
-Polygon -16777216 true false 238 112 252 141 219 141 218 112
-Circle -16777216 true false 234 174 42
-Rectangle -7500403 true true 181 185 214 194
-Circle -16777216 true false 144 174 42
-Circle -16777216 true false 24 174 42
-Circle -7500403 false true 24 174 42
-Circle -7500403 false true 144 174 42
-Circle -7500403 false true 234 174 42
-
-turtle
-true
-0
-Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
-Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
-Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
-Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
-Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
-Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99
-
-wheel
-false
-0
-Circle -7500403 true true 3 3 294
-Circle -16777216 true false 30 30 240
-Line -7500403 true 150 285 150 15
-Line -7500403 true 15 150 285 150
-Circle -7500403 true true 120 120 60
-Line -7500403 true 216 40 79 269
-Line -7500403 true 40 84 269 221
-Line -7500403 true 40 216 269 79
-Line -7500403 true 84 40 221 269
-
-wolf
-false
-0
-Polygon -16777216 true false 253 133 245 131 245 133
-Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
-Polygon -7500403 true true -1 195 14 180 36 166 40 153 53 140 82 131 134 133 159 126 188 115 227 108 236 102 238 98 268 86 269 92 281 87 269 103 269 113
-
-x
-false
-0
-Polygon -7500403 true true 270 75 225 30 30 225 75 270
-Polygon -7500403 true true 30 75 75 30 270 225 225 270
-@#$#@#$#@
-NetLogo 6.4.0
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-@#$#@#$#@
-default
-0.0
--0.2 0 0.0 1.0
-0.0 1 1.0 0.0
-0.2 0 0.0 1.0
-link direction
-true
-0
-Line -7500403 true 150 150 90 180
-Line -7500403 true 150 150 210 180
-@#$#@#$#@
-1
-@#$#@#$#@
diff --git a/demos/old-version-files/template-examples.nlogo b/demos/old-version-files/template-examples.nlogo
deleted file mode 100644
index 478e28b..0000000
--- a/demos/old-version-files/template-examples.nlogo
+++ /dev/null
@@ -1,116 +0,0 @@
-extensions [llm]
-
-globals [
- current-agent-code
- code-evolution-history
-]
-
-; Example 1: Using the code evolution template
-to example-code-evolution
- ; Set up some example data
- set current-agent-code "lt random 20 rt random 20 fd 1"
- set code-evolution-history "v1: fd 1\nv2: lt 10 fd 1\nv3: lt random 10 fd 1"
-
- ; Set up LLM (configure your provider first)
- llm:set-provider "openai" ; or your preferred provider
- llm:set-model "gpt-4"
-
- ; Use template to evolve code
- let new-code llm:chat-with-template "demos/code-evolution-template.yaml" (list
- ["current_code" current-agent-code]
- ["code_history" code-evolution-history]
- ["objective" "improve food collection efficiency"]
- ["constraints" "valid NetLogo movement commands only"]
- ["performance_notes" "current version moves randomly, needs more purpose"]
- )
-
- print (word "Original code: " current-agent-code)
- print (word "Evolved code: " new-code)
-end
-
-; Example 2: Using the analysis template
-to example-data-analysis
- ; Analyze some simulation data
- let fitness-data "Agent 1: 15, Agent 2: 23, Agent 3: 8, Agent 4: 31, Agent 5: 12"
-
- let analysis llm:chat-with-template "demos/analysis-template.yaml" (list
- ["data" fitness-data]
- ["context" "NetLogo agent fitness after 1000 ticks"]
- ["goal" "identify patterns and suggest improvements"]
- ["trends" "fitness generally increasing over generations"]
- )
-
- print "=== Fitness Analysis ==="
- print analysis
-end
-
-; Example 3: Using the reasoning template
-to example-problem-solving
- let solution llm:chat-with-template "demos/reasoning-template.yaml" (list
- ["problem" "Agents are clustering instead of spreading out to find food"]
- ["available_info" "10 agents, 50 food sources, 100x100 world"]
- ["constraints" "Cannot change world size or agent count"]
- ["success_criteria" "More even distribution and higher average fitness"]
- )
-
- print "=== Problem Solving ==="
- print solution
-end
-
-; Example 4: Using templates with agent conversations
-to example-agent-conversation
- ; Create some agents and have them use templates
- create-turtles 3 [
- set color red
- setxy random-xcor random-ycor
-
- ; Each agent gets personalized advice
- let advice llm:chat-with-template "demos/simple-template.yaml" (list
- ["task" "provide movement strategy"]
- ["input" (word "I am agent " who " at position " xcor ", " ycor)]
- ["context" "food is scattered randomly across the world"]
- )
-
- print (word "Agent " who " received: " advice)
- ]
-end
-
-; Utility function to track code evolution for an agent
-to track-my-code-evolution [new-code]
- ; Add to conversation history to track evolution
- llm:chat (word "CODE_VERSION: " new-code)
-end
-
-; Utility function to get code history for an agent
-to-report get-my-code-history
- let history llm:history
- let code-versions []
- foreach history [ msg ->
- let role item 0 msg
- let content item 1 msg
- if role = "user" and (substring content 0 13) = "CODE_VERSION:" [
- set code-versions lput (substring content 14 (length content)) code-versions
- ]
- ]
- report code-versions
-end
-
-; Example of integrating with existing mutation system
-to-report evolve-agent-code [current-code objective]
- ; Track this version
- track-my-code-evolution current-code
-
- ; Get evolution history
- let history get-my-code-history
-
- ; Use template to evolve
- let evolved-code llm:chat-with-template "demos/code-evolution-template.yaml" (list
- ["current_code" current-code]
- ["code_history" (reduce word history)]
- ["objective" objective]
- ["constraints" "NetLogo syntax only"]
- ["performance_notes" "based on fitness evaluation"]
- )
-
- report evolved-code
-end
diff --git a/demos/old-version-files/test-llm-config.nlogo b/demos/old-version-files/test-llm-config.nlogo
deleted file mode 100644
index bde3710..0000000
--- a/demos/old-version-files/test-llm-config.nlogo
+++ /dev/null
@@ -1,142 +0,0 @@
-; ABOUTME: Simple test model to debug LLM configuration issues
-; ABOUTME: Run this to verify LLM extension is working before running the main model
-
-extensions [ llm ]
-
-globals [
- test-results
-]
-
-to setup
- clear-all
- print "=== LLM Configuration Test ==="
-
- ; Test 1: Try loading config.txt
- test-config-file "demos/config"
-
- ; Test 2: Try loading config-env.txt
- test-config-file "config-env.txt"
-
- ; Test 3: Try direct configuration
- test-direct-config
-
- ; Test 4: Try environment variable
- test-env-variable
-
- print "=== Test Complete ==="
- print "Check the output above to see which configuration method works"
-end
-
-to test-config-file [filename]
- print (word "")
- print (word "Testing: " filename)
- print "------------------------"
-
- ifelse file-exists? filename [
- print (word "File found: " filename)
-
- carefully [
- llm:load-config filename
- print "Config loaded successfully"
- print (word "Provider: " llm:get-provider)
- print (word "Model: " llm:get-model)
-
- ; Try a simple test
- carefully [
- let response llm:chat "Say 'Hello' in one word"
- print (word "Test successful! Response: " response)
- ] [
- print (word "Test failed: " error-message)
- analyze-error error-message
- ]
- ] [
- print (word "Failed to load config: " error-message)
- ]
- ] [
- print (word "File not found: " filename)
- ]
-end
-
-to test-direct-config
- print (word "")
- print "Testing: Direct OpenAI Configuration"
- print "------------------------"
-
- carefully [
- llm:set-provider "openai"
- llm:set-model "gpt-4o-mini"
- print "Provider and model set"
- print "Note: This requires OPENAI_API_KEY environment variable"
-
- ; Try a simple test
- carefully [
- let response llm:chat "Say 'Hello' in one word"
- print (word "Test successful! Response: " response)
- ] [
- print (word "Test failed: " error-message)
- analyze-error error-message
- ]
- ] [
- print (word "Failed to configure: " error-message)
- ]
-end
-
-to test-env-variable
- print (word "")
- print "Testing: Environment Variable Check"
- print "------------------------"
-
- ; Note: NetLogo doesn't have direct access to environment variables
- ; but the LLM extension should check for them
- print "If you have set OPENAI_API_KEY as an environment variable,"
- print "the direct configuration test above should work."
- print ""
- print "To set environment variable:"
- print " Mac/Linux: export OPENAI_API_KEY='your-key-here'"
- print " Windows: set OPENAI_API_KEY=your-key-here"
-end
-
-to analyze-error [err]
- print "Error Analysis:"
-
- ifelse position "404" err != false [
- print " โ 404 Error: API endpoint not found"
- print " - This usually means the API URL is incorrect"
- print " - Or the API key format is wrong"
- print " - For OpenAI, ensure the key starts with 'sk-'"
- ] [
- ifelse position "401" err != false [
- print " โ 401 Error: Authentication failed"
- print " - API key is missing or invalid"
- print " - Check if the key is properly set"
- ] [
- ifelse position "429" err != false [
- print " โ 429 Error: Rate limit exceeded"
- print " - Too many requests"
- print " - Wait a bit and try again"
- ] [
- ifelse position "500" err != false [
- print " โ 500 Error: Server error"
- print " - API service is having issues"
- print " - Try again later"
- ] [
- print (word " โ Unknown error: " err)
- ]
- ]
- ]
- ]
-end
-
-to test-simple-chat
- ; Quick test button to check if LLM is working
- print ""
- print "Quick Chat Test:"
-
- carefully [
- let response llm:chat "What is 2+2? Answer in one word."
- print (word "Success! Response: " response)
- ] [
- print (word "Failed: " error-message)
- analyze-error error-message
- ]
-end
diff --git a/demos/old-version-files/test-treasure-hunt.nlogo b/demos/old-version-files/test-treasure-hunt.nlogo
deleted file mode 100644
index 532cee4..0000000
--- a/demos/old-version-files/test-treasure-hunt.nlogo
+++ /dev/null
@@ -1,41 +0,0 @@
-; ABOUTME: Simple test script to verify the emergent treasure hunt demo functionality
-; ABOUTME: Tests basic maze generation, agent creation, and simulation startup
-
-extensions [llm]
-
-; Simple test to verify the treasure hunt demo loads and runs
-to test-treasure-hunt-demo
- ; Test maze generation
- setup
-
- ; Verify basic world state
- if count treasure-hunters != 5 [
- print "ERROR: Expected 5 treasure hunters, found " count treasure-hunters
- ]
-
- ; Verify maze has walls and paths
- let wall-count count patches with [wall?]
- let path-count count patches with [not wall?]
-
- if wall-count = 0 [
- print "ERROR: No walls found in maze"
- ]
-
- if path-count = 0 [
- print "ERROR: No paths found in maze"
- ]
-
- ; Verify agents have knowledge fragments
- ask treasure-hunters [
- if knowledge-fragment = "" [
- print "ERROR: Agent missing knowledge fragment"
- ]
- ]
-
- ; Run a few ticks to test basic functionality
- repeat 10 [
- go
- ]
-
- print "Basic treasure hunt demo test completed successfully!"
-end
diff --git a/demos/tests/README.md b/demos/tests/README.md
index b3fddbc..86e4c4c 100644
--- a/demos/tests/README.md
+++ b/demos/tests/README.md
@@ -14,10 +14,33 @@ This suite is not part of default `sbt test`.
## Files
-- `tests.nlogox` - Manual test model
+- `tests.nlogox` - Manual test model (provider registry, config, primitive coverage)
+- `reliability-tests.nlogox` - Reliability regression tests against a live provider (see below)
- `config.txt.example` - Template with placeholders for all 6 providers
- `config.txt` - Local config used by the model (gitignored, create from template)
+## Reliability Tests
+
+`reliability-tests.nlogox` covers the three reliability fixes in PR #44 against a
+real provider - the behavior the deterministic `sbt test` suite cannot reach,
+because it uses a stub provider that never returns a genuine HTTP 429.
+
+| Issue | Checked by |
+|-------|-----------|
+| #33 - failed calls leave orphaned prompts in history | `test-history-unchanged-on-failure`, `test-thinking-history-unchanged-on-failure` |
+| #32 - async calls can reorder or race per-agent history | `test-async-overlapping-atomic`, `test-mixed-sync-async-atomic` |
+| #37 - rate-limit errors halt the run instead of retrying | `test-rate-limit-retry` |
+
+The history tests assert two invariants that both bugs break: history length is
+always even, and roles strictly alternate `user` / `assistant`.
+
+**Running them:**
+
+- **Run history tests** - low quota use, works on any provider including Ollama.
+- **Rate limit (10)** / **Rate limit (50)** - needs a rate-limited free tier
+ (Gemini or Groq) to actually produce 429s. Ollama will not trigger them.
+ Raise the burst size until the quota trips; the run should still complete.
+
## Prerequisites
1. Build and install the extension
diff --git a/demos/tests/config.txt.example b/demos/tests/config.txt.example
index 4408119..27c431c 100644
--- a/demos/tests/config.txt.example
+++ b/demos/tests/config.txt.example
@@ -1,47 +1,188 @@
-# NetLogo LLM Extension โ Test Configuration (Template)
+# =============================================================================
+# NetLogo LLM Extension โ Configuration
+# =============================================================================
#
-# Copy this file to `config.txt` in the same directory and fill in
-# the API key for whichever provider you want to test:
+# SETUP
+# 1. cp config.txt.example config.txt (config.txt is gitignored)
+# 2. Pick ONE provider block below, uncomment its lines
+# 3. Paste your key. No quotes around the value.
#
-# cp config.txt.example config.txt
+# RULES
+# - Exactly ONE provider block active at a time.
+# - Lines starting with # are ignored.
+# - Do NOT quote values. gemini_api_key=abc123 NOT gemini_api_key="abc123"
+# - Later duplicate keys win, so leave unused blocks commented out.
#
-# `config.txt` is gitignored so your real key stays local.
+# CHECK IT WORKED
+# print llm:active => [provider model]
+# print llm:provider-status => which providers are ready
+# print llm:list-models => models known for the active provider
+# print llm:config => full config, API keys masked
#
-# To switch providers: change `provider=` and `model=` below, then
-# uncomment the matching api_key line. Only one provider runs at a time.
+# =============================================================================
-provider=openrouter
-model=openai/gpt-4o-mini
+# =============================================================================
+# 1. OLLAMA โ local, free, no API key
+# =============================================================================
+# Install: https://ollama.com then: ollama pull llama3.2:3b
+# Best for: offline work, classrooms, zero-cost testing.
+# Note: never returns HTTP 429, so it cannot exercise rate-limit retry tests.
+
+provider=ollama
+model=llama3.2:3b
+ollama_base_url=http://localhost:11434
+
+# Models โ must be pulled locally first (`ollama list` shows yours):
+# llama3.2:3b small, fast, good default
+# llama3.2:1b fastest, lowest quality
+# llama3.3:70b large, slow, high quality
+# qwen2.5:7b solid general model
+# qwen3:0.6b tiny reasoning model
+# deepseek-r1:8b reasoning model, exposes thinking
+
+
+# =============================================================================
+# 2. GOOGLE GEMINI โ generous free tier
+# =============================================================================
+# Key: https://aistudio.google.com/apikey
+# Best for: workshops, and for testing rate-limit retry (free tier returns 429).
+
+# provider=gemini
+# model=gemini-2.5-flash
+# gemini_api_key=REPLACE_ME
+
+# Models:
+# gemini-2.5-flash fast, cheap, recommended default
+# gemini-2.5-flash-lite fastest, cheapest
+# gemini-2.5-pro highest quality, slower
+# gemini-3-flash-preview newest fast model
+# gemini-3-pro-preview newest high-end model
+
+
+# =============================================================================
+# 3. OPENAI
+# =============================================================================
+# Key: https://platform.openai.com/api-keys (keys start with sk-)
+
+# provider=openai
+# model=gpt-5-mini
+# openai_api_key=REPLACE_ME
+
+# Models:
+# gpt-5-mini cheap, fast, recommended default
+# gpt-5 newest flagship
+# gpt-5-nano cheapest
+# gpt-4.1-mini previous generation, cheap
+# gpt-4o-mini previous generation, widely available
+# o4-mini reasoning model (OpenAI hides the reasoning text)
+# o3 strongest reasoning model
+
+
+# =============================================================================
+# 4. ANTHROPIC (CLAUDE)
+# =============================================================================
+# Key: https://console.anthropic.com (keys start with sk-ant-)
+# Note: with thinking enabled, max_tokens must exceed thinking_budget_tokens.
+
+# provider=anthropic
+# model=claude-haiku-4-5-20251001
+# anthropic_api_key=REPLACE_ME
+
+# Models:
+# claude-haiku-4-5-20251001 fast, cheap, recommended default
+# claude-sonnet-4-5-20250929 balanced
+# claude-opus-4-5-20251101 highest quality
+
+
+# =============================================================================
+# 5. OPENROUTER โ one key, 200+ models across every vendor
+# =============================================================================
+# Key: https://openrouter.ai/keys
+# Best for: comparing models across vendors without separate accounts.
+
+# provider=openrouter
+# model=openai/gpt-4o-mini
+# openrouter_api_key=REPLACE_ME
+
+# Models โ always vendor-prefixed:
+# openai/gpt-4o-mini
+# openai/gpt-4.1-mini
+# anthropic/claude-sonnet-4-20250514
+# google/gemini-2.0-flash-001
+# meta-llama/llama-3.3-70b-instruct
+# deepseek/deepseek-r1 reasoning, exposes thinking
+
+
+# =============================================================================
+# 6. TOGETHER AI โ open models
+# =============================================================================
+# Key: https://api.together.xyz/settings/api-keys
+
+# provider=together
+# model=meta-llama/Llama-3.3-70B-Instruct-Turbo
+# together_api_key=REPLACE_ME
+
+# Models:
+# meta-llama/Llama-3.3-70B-Instruct-Turbo recommended default
+# meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo small and fast
+# deepseek-ai/DeepSeek-R1 reasoning model
+# Qwen/Qwen2.5-72B-Instruct-Turbo
+
+
+# =============================================================================
+# GENERATION SETTINGS โ apply to whichever provider is active
+# =============================================================================
+
+# 0.0 = deterministic, 1.0 = creative. Default 0.7.
+# Ignored for reasoning models (Anthropic forces 1.0 when thinking is on).
temperature=0.7
+
+# Max tokens in the reply. Default 1000.
+# Raise for long replies; must exceed thinking_budget_tokens when thinking is on.
max_tokens=200
+
+# Seconds to wait before giving up on a request. Default 30.
+# Raise for reasoning models and large local models โ they are slow.
timeout_seconds=60
-# --- OpenRouter (https://openrouter.ai/keys) ---
-openrouter_api_key=REPLACE_ME
-# Sample models:
-# openai/gpt-4o-mini
-# anthropic/claude-3.5-haiku
-# deepseek/deepseek-r1
-# --- Together AI (https://api.together.ai/settings/api-keys) ---
-# together_api_key=REPLACE_ME
-# Sample models:
-# meta-llama/Llama-3.3-70B-Instruct-Turbo
-# deepseek-ai/DeepSeek-R1
+# =============================================================================
+# REASONING / THINKING โ optional, all off by default
+# =============================================================================
+# Some models can return their reasoning alongside the answer:
+#
+# let result llm:chat-with-thinking "your prompt"
+# let answer item 0 result
+# let thinking item 1 result
+#
+# Auto-detection: OpenAI o-series models force thinking on automatically.
+# Every other model needs enable_thinking=true.
+#
+# Thinking is EXPOSED by: anthropic, gemini, ollama, openrouter, together
+# Thinking is HIDDEN by: openai (the API does not return reasoning tokens)
-# --- OpenAI ---
-# openai_api_key=sk-REPLACE_ME
-# model: gpt-4o-mini
+# Turn thinking on for models that support it.
+# enable_thinking=true
-# --- Anthropic (Claude) ---
-# anthropic_api_key=sk-ant-REPLACE_ME
-# model: claude-3-5-haiku-latest
+# How hard to think: none | low | medium | high | xhigh
+# Used by OpenAI, OpenRouter, Together, and Gemini.
+# reasoning_effort=medium
-# --- Google Gemini ---
-# gemini_api_key=REPLACE_ME
-# model: gemini-1.5-flash
+# Token budget for reasoning. Minimum 1024. Used by Anthropic and Gemini.
+# Must be less than max_tokens โ raise max_tokens to match.
+# thinking_budget_tokens=2048
+
+
+# =============================================================================
+# ADVANCED โ override API endpoints
+# =============================================================================
+# Only needed for proxies, self-hosted gateways, or a non-default Ollama host.
+# Defaults shown; each provider has its own key.
-# --- Ollama (local) ---
+# openai_base_url=https://api.openai.com/v1
+# anthropic_base_url=https://api.anthropic.com/v1
+# gemini_base_url=https://generativelanguage.googleapis.com/v1beta
# ollama_base_url=http://localhost:11434
-# model: llama3.2
+# openrouter_base_url=https://openrouter.ai/api/v1
+# together_base_url=https://api.together.xyz/v1
diff --git a/demos/emergent-treasure-hunt/new-model.nlogox b/demos/tests/reliability-tests.nlogox
similarity index 60%
rename from demos/emergent-treasure-hunt/new-model.nlogox
rename to demos/tests/reliability-tests.nlogox
index fb6ec84..5fd75aa 100644
--- a/demos/emergent-treasure-hunt/new-model.nlogox
+++ b/demos/tests/reliability-tests.nlogox
@@ -1,800 +1,403 @@
-
-
+ = 0 [
- let west-patch patch (pxcor - 2) pycor
- if west-patch != nobody and [wall?] of west-patch [
- set possible-directions lput west-patch possible-directions
- ]
- ]
-
- if pycor - 2 >= 0 [
- let south-patch patch pxcor (pycor - 2)
- if south-patch != nobody and [wall?] of south-patch [
- set possible-directions lput south-patch possible-directions
- ]
- ]
-
- ; Randomly visit unvisited neighbors
- while [length possible-directions > 0] [
- let next-patch one-of possible-directions
- set possible-directions remove next-patch possible-directions
-
- if [wall?] of next-patch [
- ; Carve path to next cell
- let between-patch patch (([pxcor] of next-patch + pxcor) / 2) (([pycor] of next-patch + pycor) / 2)
- ask between-patch [
- set wall? false
- set pcolor brown + 1
- ]
-
- ; Recursively carve from next cell
- carve-maze-from next-patch
- ]
- ]
- ]
+to section [ name ]
+ print ""
+ print (word "=== " name " ===")
end
-to create-meeting-areas
- ; Create some larger open areas where agents can meet
- let meeting-spots []
- repeat 3 [
- let spot one-of patches with [not wall? and pxcor > 2 and pxcor < maze-width - 3 and pycor > 2 and pycor < maze-height - 3]
- if spot != nobody [
- ask spot [
- ask patches in-radius 1 [
- if wall? [
- set wall? false
- set pcolor brown + 2 ; slightly different color for meeting areas
- ]
- ]
- ]
- set meeting-spots lput spot meeting-spots
- ]
- ]
+to reset-counts
+ set pass-count 0
+ set fail-count 0
end
-to add-maze-complexity
- ; Add some additional paths to make the maze more interesting
- repeat 5 [
- let wall-patch one-of patches with [wall? and count neighbors with [not wall?] >= 2]
- if wall-patch != nobody [
- ask wall-patch [
- set wall? false
- set pcolor brown + 1
- ]
- ]
- ]
+to summary
+ print ""
+ print (word "TOTAL: " pass-count " passed, " fail-count " failed")
+ ifelse fail-count = 0
+ [ print "RESULT: ALL PASS" ]
+ [ print "RESULT: FAILURES PRESENT" ]
end
-to setup-hunter
- ; Place hunter at a random open patch
- let open-patches patches with [not wall?]
- if any? open-patches [
- move-to one-of open-patches
- ]
-
- ; Assign unique knowledge fragment
- set knowledge-fragment assign-knowledge-fragment
- set learned-facts []
- set current-goal "explore"
- set confidence-level 0
- set last-communication 0
- set memory-trail []
-
- ; Visual appearance with unique shapes and colors
- set shape one-of ["person" "circle" "triangle" "square" "star"]
- set color one-of [red blue green yellow magenta cyan orange pink]
- set size 0.9
-
- ; Set exploration strategy
- ifelse default-strategy = "mixed" [
- set exploration-strategy one-of ["methodical" "random" "wall-follower"]
- ] [
- set exploration-strategy default-strategy
- ]
-
- ; Enable pen for trail with agent's color (based on switch)
- ifelse show-trails? = true [
- pen-down
- set pen-size 2
- ] [
- pen-up
- ]
-
- ; Log agent creation
- print (word "Hunter " who " created with clue: \"" knowledge-fragment "\"")
- print (word " Strategy: " exploration-strategy ", Starting at (" pxcor ", " pycor ")")
+;; History is a list of [role content] pairs. A well-formed history always has
+;; an even length: every user message is matched by an assistant reply.
+to-report history-balanced?
+ report (length llm:history) mod 2 = 0
end
-to-report assign-knowledge-fragment
- ; Each agent gets one piece of the treasure puzzle
- let fragments [
- "The treasure is golden and round like the sun"
- "Look where two main paths cross each other"
- "The special place has coordinates that add up to exactly 15"
- "It only appears when all clues are combined"
- "The treasure glows and makes everyone happy"
- "Find the spot furthest from any wall"
- ]
-
- ; Assign unique fragments (cycle through if more agents than fragments)
- let my-index who mod length fragments
- report item my-index fragments
+to-report roles-of [ hist ]
+ report map [ pair -> item 0 pair ] hist
end
-to setup-visual-appearance
- ; Set patch colors and visual effects
- ask patches [
- if not wall? [
- set path-color brown + 1
- ]
- ]
-
- ; Create visual border
- ask patches with [pxcor = 0 or pxcor = maze-width - 1 or pycor = 0 or pycor = maze-height - 1] [
- set pcolor black
+;; Verify strict user/assistant alternation from the head of the history.
+to-report history-alternates?
+ let roles roles-of llm:history
+ let i 0
+ let ok? true
+ while [ i < length roles ] [
+ let expected ifelse-value (i mod 2 = 0) [ "user" ] [ "assistant" ]
+ if item i roles != expected [ set ok? false ]
+ set i i + 1
]
+ report ok?
end
-to go
- ; Main simulation loop
- if not any? treasure-hunters [ stop ]
-
- ; Agent actions
- ask treasure-hunters [
- move-through-maze
- detect-nearby-agents
- analyze-current-situation
- take-action-based-on-goal
- update-exploration-memory
- update-agent-appearance
- ]
-
- ; Update environment
- update-visual-effects
- check-treasure-conditions
+;; ---------------------------------------------------------------------------
+;; Setup
+;; ---------------------------------------------------------------------------
- tick
-
- ; Stop if treasure is found and celebrated
- if treasure-discovered? and any? treasures [
- if ticks mod 30 = 0 [ ; celebration effect every 30 ticks
- celebrate-success
- ]
- ]
+to setup
+ clear-all
+ reset-counts
+ llm:load-config "config.txt"
+ print (word "Provider: " llm:active)
+ reset-ticks
end
-to move-through-maze
- ; Different movement strategies
- if exploration-strategy = "random" [
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
-
- if exploration-strategy = "methodical" [
- ; Try to explore unseen areas
- let unexplored patches with [not wall? and not explored? and distance myself <= 1]
- ifelse any? unexplored [
- move-to one-of unexplored
+;; ---------------------------------------------------------------------------
+;; Issue #33 โ a failed call must not leave an orphaned prompt in history
+;;
+;; Before the fix, llm:chat appended the user message before the request and
+;; never rolled it back on failure, leaving an odd-length history where the
+;; last user message had no reply. Every later call then sent a malformed
+;; conversation.
+;;
+;; Forced failure here uses an impossible model name so the request errors at
+;; the provider rather than locally.
+;; ---------------------------------------------------------------------------
+
+to test-history-unchanged-on-failure
+ section "#33 history integrity on failure"
+
+ clear-turtles
+ create-turtles 1
+ ask turtle 0 [
+ llm:clear-history
+
+ ;; One good exchange: history should be exactly [user assistant].
+ let ok-reply llm:chat "Reply with the single word: ready"
+ assert-true (length llm:history = 2) "successful call commits one pair"
+ assert-true history-balanced? "history balanced after success"
+
+ let len-before length llm:history
+
+ ;; Force a provider-side failure.
+ let saved-model item 1 llm:active
+ llm:set-model "definitely-not-a-real-model-xyz"
+ carefully [
+ let doomed llm:chat "This request is expected to fail."
+ test-fail "expected failure did not occur (check model name is invalid)"
] [
- ; If no unexplored nearby, move randomly
- let possible-moves patches with [not wall? and distance myself <= 1]
- if any? possible-moves [
- move-to one-of possible-moves
- ]
- ]
- ]
-
- if exploration-strategy = "wall-follower" [
- ; Follow walls (right-hand rule) - safe implementation
- right 90
- while [patch-ahead 1 = nobody or [wall?] of patch-ahead 1] [
- right 90
- ]
- ; Only move if destination is valid and not a wall
- let target-patch patch-ahead 1
- if target-patch != nobody and not [wall?] of target-patch [
- move-to target-patch
- ]
- ]
-
- ; Mark current location as explored
- ask patch-here [
- set explored? true
- set pcolor path-color + 0.5 ; slightly brighter for explored areas
- ]
-end
-
-to detect-nearby-agents
- ; Check for other agents within communication range
- let nearby-hunters other treasure-hunters in-radius communication-range
-
- if any? nearby-hunters and (ticks - last-communication) > 5 [
- let communication-partner one-of nearby-hunters
-
- ; Enhanced visual effect for communication
- ask patch-here [
- set meeting-glow 15 ; bright glow effect
- set pcolor yellow
- ]
-
- ; Create spreading communication effect
- ask patches in-radius 1.5 [
- if not wall? [
- set meeting-glow 8
- set pcolor yellow - 1
- ]
- ]
-
- ; Visual connection between communicating agents
- ask communication-partner [
- set color color + 3 ; brighten communicating agent
- pen-up
- move-to patch-here
- pen-down
- move-to [patch-here] of myself
- pen-up
- ]
-
- ; Initiate LLM-based conversation
- communicate-with communication-partner
- set last-communication ticks
- ]
-end
-
-to communicate-with [partner]
- ; Share knowledge using LLM
- let my-info (word knowledge-fragment ". I have learned: " learned-facts)
- let partner-info (word [knowledge-fragment] of partner ". They have learned: " [learned-facts] of partner)
- let combined-info (word "I know: " my-info ". My partner knows: " partner-info)
-
- ; Log the interaction
- print (word "=== AGENT INTERACTION at tick " ticks " ===")
- print (word "Hunter " who " meets Hunter " [who] of partner)
- print (word "Location: (" pxcor ", " pycor ")")
- print "Sharing knowledge..."
-
- ; Use LLM to synthesize information
- let conversation-result ""
- carefully [
- print "Consulting LLM for insights..."
- set conversation-result llm:chat (word combined-info ". What can we conclude about finding a treasure? Give me new insights.")
- print (word "LLM Response: " conversation-result)
- ] [
- ; If LLM call fails, log the error details
- print (word "ERROR: LLM call failed with: " error-message)
- print "Falling back to simple combination"
- set conversation-result (word "Combining clues: " [knowledge-fragment] of partner)
- ]
-
- ; Update learned facts
- if conversation-result != "" [
- set learned-facts lput conversation-result learned-facts
- print (word "Hunter " who " learned: " conversation-result)
-
- ; Partner also learns
- ask partner [
- set learned-facts lput conversation-result learned-facts
- print (word "Hunter " who " also learned this insight")
+ test-pass "failed call raised an error as expected"
]
- ]
-
- ; Update confidence based on information gained
- set confidence-level confidence-level + 0.2
- if confidence-level > 1 [ set confidence-level 1 ]
- print (word "Confidence levels updated. Hunter " who ": " precision confidence-level 2)
- print "================================"
-end
-
-to analyze-current-situation
- ; Use LLM to determine next goal based on current knowledge
- if length learned-facts > 1 and confidence-level > 0.3 [
- let situation-summary (word "My original clue: " knowledge-fragment
- ". What I've learned from others: " learned-facts
- ". I'm currently at coordinates " pxcor " " pycor
- ". What should be my next goal?")
+ llm:set-model saved-model
- let possible-goals ["explore-more" "find-center" "find-crossing" "search-systematically" "gather-more-info"]
+ assert-true (length llm:history = len-before) "history length unchanged after failure"
+ assert-true history-balanced? "no orphaned user message left behind"
+ assert-true history-alternates? "roles still alternate user/assistant"
+ ;; The next call must still succeed โ proof the history was not corrupted.
carefully [
- print (word "Hunter " who " analyzing situation...")
- let old-goal current-goal
- set current-goal llm:choose situation-summary possible-goals
- if current-goal != old-goal [
- print (word "Hunter " who " changed goal from '" old-goal "' to '" current-goal "'")
- ]
+ let recovery llm:chat "Reply with the single word: recovered"
+ assert-true (is-string? recovery and not empty? recovery) "next call succeeds after a failure"
+ assert-true history-balanced? "history balanced after recovery"
] [
- ; Fallback if LLM fails
- print (word "ERROR in goal analysis: " error-message)
- set current-goal one-of possible-goals
- print (word "Hunter " who " randomly selected goal: " current-goal)
+ test-fail (word "call after failure errored: " error-message)
]
]
end
-to take-action-based-on-goal
- ; Act based on current goal
- if current-goal = "find-center" [
- ; Move toward center of maze
- let center-patch patch (maze-width / 2) (maze-height / 2)
- if center-patch != nobody [
- face center-patch
- ]
- ]
-
- if current-goal = "find-crossing" [
- ; Look for intersection points
- let crossings patches with [not wall? and count neighbors with [not wall?] >= 3]
- if any? crossings [
- let nearest-crossing min-one-of crossings [distance myself]
- face nearest-crossing
- ]
- ]
-
- if current-goal = "search-systematically" [
- ; Check if current location matches learned criteria
- check-treasure-location
- ]
-end
+;; ---------------------------------------------------------------------------
+;; Issue #33 โ same guarantee for llm:chat-with-thinking
+;;
+;; This primitive had the same defect and its own code path, so it needs its
+;; own check.
+;; ---------------------------------------------------------------------------
-to check-treasure-location
- ; Check if current location might be treasure location based on accumulated knowledge
- let location-matches? false
+to test-thinking-history-unchanged-on-failure
+ section "#33 thinking-primitive history integrity"
- ; Analyze learned facts to see if current location fits
- if length learned-facts > 2 [
- let location-description (word "I am at coordinates " pxcor " " pycor
- ". The sum is " (pxcor + pycor)
- ". This location has " count neighbors with [not wall?] " open neighbors."
- ". Based on what I know: " learned-facts
- ". Could this be the treasure location?")
+ clear-turtles
+ create-turtles 1
+ ask turtle 0 [
+ llm:clear-history
+ let len-before length llm:history
+ let saved-model item 1 llm:active
+ llm:set-model "definitely-not-a-real-model-xyz"
carefully [
- let location-assessment llm:choose location-description ["yes-likely" "no-unlikely" "need-more-info"]
- if location-assessment = "yes-likely" [
- set location-matches? true
- ]
+ let doomed llm:chat-with-thinking "This request is expected to fail."
+ test-fail "expected failure did not occur"
] [
- ; Simple fallback check
- if (pxcor + pycor) = 15 and count neighbors with [not wall?] >= 3 [
- set location-matches? true
- ]
+ test-pass "chat-with-thinking failure raised as expected"
]
- ]
+ llm:set-model saved-model
- ; If location seems right and we have enough knowledge, try to manifest treasure
- if location-matches? and confidence-level > confidence-threshold [
- attempt-treasure-manifestation
+ assert-true (length llm:history = len-before) "thinking: history unchanged after failure"
+ assert-true history-balanced? "thinking: no orphaned prompt"
]
end
-to attempt-treasure-manifestation
- ; Try to make treasure appear based on collective knowledge
- if not treasure-discovered? [
- print "=== TREASURE MANIFESTATION ATTEMPT ==="
- print (word "Hunter " who " attempting to manifest treasure at (" pxcor ", " pycor ")")
-
- let all-knowledge []
- ask treasure-hunters [
- set all-knowledge lput knowledge-fragment all-knowledge
- set all-knowledge sentence all-knowledge learned-facts
- ]
-
- let combined-knowledge reduce word all-knowledge
- print "Combining all collective knowledge..."
-
- carefully [
- print "Asking LLM to describe the treasure..."
- let treasure-description llm:chat (word "Based on all our clues: " combined-knowledge
- ". What exactly is the treasure and what does it look like?")
- print (word "LLM treasure description: " treasure-description)
-
- if length treasure-description > 10 [ ; Got a substantial description
- set treasure-definition treasure-description
- set treasure-location patch-here
- print (word "TREASURE MANIFESTED! " treasure-definition)
- manifest-treasure
- ]
- ] [
- ; Fallback treasure manifestation
- print (word "ERROR in treasure description: " error-message)
- print "Checking if we have enough clues for fallback..."
- if length all-knowledge > 4 [ ; Enough clues gathered
- set treasure-definition "A glowing golden orb that brings joy"
- set treasure-location patch-here
- print "TREASURE MANIFESTED using fallback description!"
- manifest-treasure
- ]
- ]
- print "================================"
+;; ---------------------------------------------------------------------------
+;; Issue #32 โ overlapping async calls must commit atomic user/assistant pairs
+;;
+;; Before the fix, two async calls in flight for the same agent could interleave
+;; as user1, user2, assistant2, assistant1 โ silently scrambling the transcript.
+;; Ordering across pairs follows completion order by design; what must hold is
+;; that each pair stays contiguous and roles alternate.
+;; ---------------------------------------------------------------------------
+
+to test-async-overlapping-atomic
+ section "#32 overlapping async pairs stay atomic"
+
+ clear-turtles
+ create-turtles 1
+ ask turtle 0 [
+ llm:clear-history
+
+ ;; Fire both before awaiting either โ this is what forces the overlap.
+ let p1 llm:chat-async "Reply with the single word: alpha"
+ let p2 llm:chat-async "Reply with the single word: beta"
+
+ assert-true (is-anonymous-reporter? p1) "async returns an anonymous reporter"
+
+ let r1 runresult p1
+ let r2 runresult p2
+
+ assert-true (is-string? r1 and not empty? r1) "first async call returned a reply"
+ assert-true (is-string? r2 and not empty? r2) "second async call returned a reply"
+ assert-true (length llm:history = 4) "both pairs committed (4 messages)"
+ assert-true history-balanced? "async history balanced"
+ assert-true history-alternates? "async pairs did not interleave"
]
end
-to manifest-treasure
- ; Create the treasure at the determined location
- set treasure-discovered? true
-
- ask treasure-location [
- sprout-treasures 1 [
- set shape "circle"
- set color yellow
- set size 1.2
- set glow-phase 0
- set discovered-by nobody
- ]
- set pcolor (yellow + 2) ; golden color
- ]
+;; ---------------------------------------------------------------------------
+;; Issue #32 โ mixed sync and async on the same agent
+;; ---------------------------------------------------------------------------
- ; Visual celebration
- ask treasure-hunters [
- set color color + 2 ; brighten colors
- face treasure-location
- ]
-end
+to test-mixed-sync-async-atomic
+ section "#32 mixed sync/async integrity"
-to update-exploration-memory
- ; Track where agent has been
- if not member? patch-here memory-trail [
- set memory-trail lput patch-here memory-trail
- ]
+ clear-turtles
+ create-turtles 1
+ ask turtle 0 [
+ llm:clear-history
+
+ let pending llm:chat-async "Reply with the single word: async"
+ let sync-reply llm:chat "Reply with the single word: sync"
+ let async-reply runresult pending
- ; Keep memory manageable
- if length memory-trail > 50 [
- set memory-trail but-first memory-trail
+ assert-true (is-string? sync-reply and not empty? sync-reply) "sync call returned"
+ assert-true (is-string? async-reply and not empty? async-reply) "async call returned"
+ assert-true (length llm:history = 4) "both exchanges committed"
+ assert-true history-alternates? "mixed sync/async roles alternate"
]
end
-to update-agent-appearance
- ; Visual feedback based on confidence level
- let base-color color
+;; ---------------------------------------------------------------------------
+;; Multi-agent isolation โ each turtle keeps its own history
+;; ---------------------------------------------------------------------------
- ; Size increases with confidence
- set size (0.9 + 0.4 * confidence-level)
+to test-multi-agent-history-isolation
+ section "per-agent history isolation"
- ; Brightness increases with confidence
- if confidence-level > 0.5 [
- set color (base-color + 2)
+ clear-turtles
+ create-turtles 3
+ ask turtles [
+ llm:clear-history
+ let r llm:chat (word "Reply with the single word: agent" who)
]
-
- ; High-confidence agents get special effects
- if confidence-level > 0.8 [
- ; Create halo effect around high-confidence agents
- ask patches in-radius 1 [
- if not wall? and meeting-glow <= 0 [
- set pcolor (pcolor + 0.5)
- ]
- ]
+ ask turtles [
+ assert-true (length llm:history = 2) (word "turtle " who " has exactly its own pair")
+ assert-true history-balanced? (word "turtle " who " history balanced")
]
end
-to update-visual-effects
- ; Update meeting glow effects
- ask patches with [meeting-glow > 0] [
- set meeting-glow meeting-glow - 1
- if meeting-glow <= 0 [
- set pcolor path-color
- if explored? [ set pcolor path-color + 0.5 ]
+;; ---------------------------------------------------------------------------
+;; Issue #37 โ rate-limit (429) retry with exponential backoff
+;;
+;; This is the test that cannot be covered by the deterministic suite: it needs
+;; a real provider actually returning 429. Use a free-tier key (Gemini or Groq)
+;; and enough concurrent agents to exceed the per-minute quota.
+;;
+;; Before the fix a 429 halted the run. After it, requests retry with backoff
+;; (1s, 2s, 4s, capped at 10s, honouring Retry-After) and the run completes.
+;;
+;; Set burst-size high enough to trip the quota for your provider.
+;; ---------------------------------------------------------------------------
+
+to test-rate-limit-retry [ burst-size ]
+ section (word "#37 rate-limit retry (burst of " burst-size ")")
+
+ clear-turtles
+ create-turtles burst-size
+ set start-ms timer
+
+ let errors 0
+ let replies 0
+
+ ask turtles [
+ llm:clear-history
+ carefully [
+ let r llm:chat "Reply with one word: ok"
+ if is-string? r and not empty? r [ set replies replies + 1 ]
+ ] [
+ set errors errors + 1
+ print (word " error on turtle " who ": " error-message)
]
]
- ; Enhanced treasure glow and surrounding effects
- if any? treasures [
- ask treasures [
- set glow-phase glow-phase + 0.3
- ; Pulsing treasure colors
- set color (yellow + 2 + 2 * sin(glow-phase * 180)) ; pulsing golden
- set size (1.2 + 0.3 * sin(glow-phase * 90))
-
- ; Treasure radiates light to surrounding patches
- ask patches in-radius 2 [
- if not wall? [
- let distance-from-treasure distance myself
- let glow-intensity (3 - distance-from-treasure) / 3
- set pcolor (yellow + glow-intensity * 2) ; golden glow
- ]
- ]
-
- ; Sparkle effect
- if random 10 < 3 [
- ask one-of patches in-radius 1.5 with [not wall?] [
- set pcolor white
- set meeting-glow 3
- ]
- ]
- ]
- ]
-end
+ let elapsed timer - start-ms
+ print (word " " replies "/" burst-size " replies in " (precision elapsed 1) "s")
-to check-treasure-conditions
- ; Check if treasure has been found by agents
- if treasure-discovered? and any? treasures [
- let treasure-patch [patch-here] of one-of treasures
- let hunters-at-treasure treasure-hunters-on treasure-patch
+ assert-true (errors = 0) "no agent aborted with a rate-limit error"
+ assert-true (replies = burst-size) "every agent received a reply"
- if any? hunters-at-treasure [
- ask one-of treasures [
- set discovered-by hunters-at-treasure
- ]
- ]
+ ;; Backoff makes a rate-limited burst measurably slower than an unthrottled
+ ;; one. This is informational, not a pass/fail signal.
+ if elapsed > burst-size [
+ print " (elapsed time suggests backoff was exercised)"
]
end
-to celebrate-success
- ; Visual celebration when treasure is found
- if any? treasures [
- ask one-of treasures [
- ask patches in-radius 3 [
- set pcolor (pcolor + random 3 - 1)
- ]
- ]
+;; Convenience wrappers for interface buttons.
+to test-rate-limit-small
+ test-rate-limit-retry 10
+end
- ask treasure-hunters [
- right random 60 - 30 ; dance movement
- ]
- ]
+to test-rate-limit-large
+ test-rate-limit-retry 50
end
-; Utility reporters
-to-report knowledge-summary
- ; Report summary of all agent knowledge
- let summary ""
- ask treasure-hunters [
- set summary (word summary "Agent " who ": " knowledge-fragment " | ")
- ]
- report summary
+;; ---------------------------------------------------------------------------
+;; Runners
+;; ---------------------------------------------------------------------------
+
+;; Everything except the rate-limit burst โ safe on any provider, low quota use.
+to run-history-tests
+ setup
+ test-history-unchanged-on-failure
+ test-thinking-history-unchanged-on-failure
+ test-async-overlapping-atomic
+ test-mixed-sync-async-atomic
+ test-multi-agent-history-isolation
+ summary
end
-to-report treasure-status
- ; Report current treasure discovery status
- if treasure-discovered? [
- report (word "DISCOVERED: " treasure-definition)
- ]
- report "Still searching..."
-end]]>
+;; Full suite including the rate-limit burst. Uses significant quota.
+to run-all-tests
+ setup
+ test-history-unchanged-on-failure
+ test-thinking-history-unchanged-on-failure
+ test-async-overlapping-atomic
+ test-mixed-sync-async-atomic
+ test-multi-agent-history-isolation
+ test-rate-limit-small
+ summary
+end
+]]>
-
-
-
-
-
-
-
-
-
- set-current-plot "Agent Confidence"
-create-temporary-plot-pen "confidence"
-set-plot-pen-color blue
- if any? treasure-hunters [
- plot mean [confidence-level] of treasure-hunters
-]
-
-
-
-
-
-
-
- if any? treasure-hunters [
- plot sum [length learned-facts] of treasure-hunters
-]
-
-
-
-
-
-
-
-
- demos/config
-
- treasure-status
- count treasure-hunters
- ticks
-
-
-
- knowledge-summary
-
+
+
+
+
+
+
+ pass-count
+ fail-count
## WHAT IS IT?
-(a general understanding of what the model is trying to show or explain)
+Live-provider reliability tests for the NetLogo LLM extension. This model exercises
+the three reliability fixes in PR #44 against a **real** provider, covering the
+behaviour the deterministic `sbt test` suite cannot reach.
+
+- **#33** - a failed call must not leave an orphaned prompt in an agent's history
+- **#32** - overlapping async calls must not race or scramble per-agent history
+- **#37** - rate-limit (HTTP 429) errors must retry with backoff, not halt the run
## HOW IT WORKS
-(what rules the agents use to create the overall behavior of the model)
+Each test drives the extension through a scenario and asserts on `llm:history`.
+
+A well-formed history always has an even length and strictly alternates
+`user` / `assistant`. Both invariants break under the bugs above, so they are
+what the assertions check.
+
+The #33 tests force a provider-side failure by temporarily setting an invalid
+model name, then confirm the history is byte-for-byte unchanged and that the
+next call still succeeds.
+
+The #32 tests fire two async calls before awaiting either, forcing the overlap,
+then confirm both user/assistant pairs committed contiguously. Note that
+ordering *across* pairs follows completion order by design - the guarantee is
+that each pair stays atomic, not that call order is preserved.
+
+The #37 test issues a burst of concurrent requests large enough to exceed a
+free-tier quota. Before the fix the run aborted on the first 429; after it,
+requests retry with exponential backoff and every agent receives a reply.
## HOW TO USE IT
-(how to use the model, including a description of each of the items in the Interface tab)
+1. Build and install the extension (`./build.sh`).
+2. Copy `config.txt.example` to `config.txt` and set a provider plus a real key.
+3. Click **setup**, then **run history tests** for the low-quota checks.
+4. For #37, use a rate-limited free tier (Gemini or Groq) and click
+ **rate limit (10)** or **rate limit (50)**. Ollama will not produce 429s.
+
+Results print to the Command Center. The run ends with a PASS/FAIL total.
## THINGS TO NOTICE
-(suggested things for the user to notice while running the model)
+The rate-limit test prints elapsed time. A burst that trips the quota takes
+noticeably longer than one that does not - that gap is the backoff working.
+Watch for retry messages on stderr.
## THINGS TO TRY
-(suggested things for the user to try to do (move sliders, switches, etc.) with the model)
-
-## EXTENDING THE MODEL
+Check out the branch before PR #44 and run the same tests: #33 leaves an
+odd-length history, and #37 aborts the run on the first 429.
-(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)
+Raise the burst size until the quota trips, and confirm the run still completes.
-## NETLOGO FEATURES
+## EXTENDING THE MODEL
-(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)
+Add cases for `llm:chat-with-template` failure paths, or for history behaviour
+under `clear-all` mid-run.
## RELATED MODELS
-(models in the NetLogo Models Library and elsewhere which are of related interest)
+`demos/tests/tests.nlogox` - broader manual integration suite covering provider
+registry, config, and primitive coverage across all six providers.
## CREDITS AND REFERENCES
-(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)
+NetLogo LLM Extension, Center for Connected Learning, Northwestern University.
@@ -1629,5 +1232,5 @@ set-plot-pen-color blue
- setup repeat 75 [ go ]
+ setup
diff --git a/src/main/LLMExtension.scala b/src/main/LLMExtension.scala
index 862caad..821d51f 100644
--- a/src/main/LLMExtension.scala
+++ b/src/main/LLMExtension.scala
@@ -55,7 +55,11 @@ class LLMExtension extends DefaultClassManager {
// Per-agent conversation history
private val messageHistory: WeakHashMap[Agent, ArrayBuffer[ChatMessage]] = WeakHashMap()
-
+
+ // Guards messageHistory and every contained buffer. Never held across Await
+ // or provider calls; critical sections are small snapshots/appends only.
+ private val historyLock = new Object
+
// Execution context for async operations
implicit private val ec: ExecutionContext = ExecutionContext.global
@@ -122,7 +126,7 @@ class LLMExtension extends DefaultClassManager {
* Called when NetLogo calls clear-all or when the model is reset
*/
override def clearAll(): Unit = {
- messageHistory.clear()
+ historyLock.synchronized { messageHistory.clear() }
}
/**
@@ -143,12 +147,32 @@ class LLMExtension extends DefaultClassManager {
}
/**
- * Get or create conversation history for an agent
+ * Get or create conversation history for an agent.
+ * Callers must hold historyLock โ the buffer must not escape a locked section.
*/
private def getAgentHistory(agent: Agent): ArrayBuffer[ChatMessage] = {
messageHistory.getOrElseUpdate(agent, ArrayBuffer.empty[ChatMessage])
}
+ /**
+ * Immutable snapshot of an agent's history, safe to build a request from
+ * while other threads mutate the live buffer.
+ */
+ private def snapshotHistory(agent: Agent): Seq[ChatMessage] =
+ historyLock.synchronized { getAgentHistory(agent).toSeq }
+
+ /**
+ * Append a user/assistant exchange to an agent's history atomically.
+ * Re-resolves the buffer by agent so a commit racing set-history lands in
+ * the current buffer, not a detached stale one.
+ */
+ private def commitExchange(agent: Agent, user: ChatMessage, assistant: ChatMessage): Unit =
+ historyLock.synchronized {
+ val h = getAgentHistory(agent)
+ h += user
+ h += assistant
+ }
+
/**
* Get timeout from config, falling back to 30 seconds
*/
@@ -433,17 +457,15 @@ class LLMExtension extends DefaultClassManager {
try {
val provider = ensureProvider()
- val history = getAgentHistory(agent)
val userMessage = ChatMessage.user(inputText)
// Send chat request with user message included, but don't mutate history yet
- val responseFuture = provider.chat(history.toSeq :+ userMessage)
+ val responseFuture = provider.chat(snapshotHistory(agent) :+ userMessage)
val responseMessage = Await.result(responseFuture, getTimeoutSeconds.seconds)
- // Only append both messages after success
- history += userMessage
- history += responseMessage
+ // Only commit both messages after success
+ commitExchange(agent, userMessage, responseMessage)
responseMessage.content
@@ -466,15 +488,13 @@ class LLMExtension extends DefaultClassManager {
try {
val provider = ensureProvider()
- val history = getAgentHistory(agent)
val userMessage = ChatMessage.user(inputText)
- // Send with user message included, but don't mutate history yet
- val responseFuture = provider.chat(history.toSeq :+ userMessage).map { responseMessage =>
- // Append both atomically on success
- history += userMessage
- history += responseMessage
+ // Snapshot on the NetLogo thread; commit the pair atomically on success
+ // from the completion thread so overlapping async calls can't interleave.
+ val responseFuture = provider.chat(snapshotHistory(agent) :+ userMessage).map { responseMessage =>
+ commitExchange(agent, userMessage, responseMessage)
responseMessage.content
}
@@ -501,7 +521,6 @@ class LLMExtension extends DefaultClassManager {
try {
val provider = ensureProvider()
- val history = getAgentHistory(agent)
// Extract model directory from workspace
val modelDir = Option(context.workspace.getModelPath).flatMap { path =>
@@ -521,23 +540,22 @@ class LLMExtension extends DefaultClassManager {
val processedTemplate = substituteVariables(template.template, variables)
// Build a copy so temporary prompt assembly never mutates permanent history.
- val tempHistory = ArrayBuffer.from(history)
+ val tempHistory = ArrayBuffer.from(snapshotHistory(agent))
if (template.system.nonEmpty) {
tempHistory.prepend(ChatMessage.system(template.system))
}
-
+
// Add user message with processed template
val userMessage = ChatMessage.user(processedTemplate)
tempHistory += userMessage
-
+
// Send chat request
val responseFuture = provider.chat(tempHistory.toSeq)
val responseMessage = Await.result(responseFuture, getTimeoutSeconds.seconds)
-
- // Add both template message and response to permanent history
- history += userMessage
- history += responseMessage
-
+
+ // Commit both template message and response to permanent history on success
+ commitExchange(agent, userMessage, responseMessage)
+
responseMessage.content
} catch {
@@ -560,7 +578,6 @@ class LLMExtension extends DefaultClassManager {
try {
val provider = ensureProvider()
- val history = getAgentHistory(agent)
val choices = choicesList.map(_.toString).toList
@@ -578,7 +595,7 @@ class LLMExtension extends DefaultClassManager {
"Your choice (one option, no other text):"
// Build temp history with system prompt โ don't mutate permanent history
- val tempHistory = ArrayBuffer.from(history)
+ val tempHistory = ArrayBuffer.from(snapshotHistory(agent))
tempHistory.prepend(ChatMessage.system(systemPrompt))
tempHistory += ChatMessage.user(userPrompt)
@@ -602,8 +619,7 @@ class LLMExtension extends DefaultClassManager {
}
// Only on success: store clean messages in permanent history
- history += ChatMessage.user(prompt)
- history += ChatMessage.assistant(chosenOption)
+ commitExchange(agent, ChatMessage.user(prompt), ChatMessage.assistant(chosenOption))
chosenOption
@@ -628,21 +644,18 @@ class LLMExtension extends DefaultClassManager {
try {
val provider = ensureProvider()
- val history = getAgentHistory(agent)
- // Add user message to history
val userMessage = ChatMessage.user(inputText)
- history += userMessage
- // Send chat request and get full response with thinking
- val responseFuture = provider.chatWithFullResponse(history.toSeq)
+ // Send with user message included, but don't mutate history yet
+ val responseFuture = provider.chatWithFullResponse(snapshotHistory(agent) :+ userMessage)
val response = Await.result(responseFuture, getTimeoutSeconds.seconds)
val answerText = response.firstContent.getOrElse("")
val thinkingText = response.thinking.getOrElse("")
- // Only add the clean answer to history (not thinking text)
- history += ChatMessage.assistant(answerText)
+ // Only commit both messages after success (clean answer only, not thinking text)
+ commitExchange(agent, userMessage, ChatMessage.assistant(answerText))
// Return [answer thinking] list โ always 2 elements
LogoList(answerText, thinkingText)
@@ -704,8 +717,8 @@ class LLMExtension extends DefaultClassManager {
override def report(args: Array[Argument], context: Context): LogoList = {
val agent = context.getAgent
- val history = getAgentHistory(agent)
-
+ val history = snapshotHistory(agent)
+
LogoList.fromIterator(
history.map { message =>
LogoList(message.role, message.content)
@@ -728,9 +741,9 @@ class LLMExtension extends DefaultClassManager {
case _ =>
throw new ExtensionException("History items must be lists of [role content] pairs")
}.to(ArrayBuffer)
-
- messageHistory.put(agent, messages)
-
+
+ historyLock.synchronized { messageHistory.put(agent, messages) }
+
} catch {
case e: Exception if !e.isInstanceOf[ExtensionException] =>
throw new ExtensionException(s"Invalid history format: ${e.getMessage}")
@@ -743,7 +756,7 @@ class LLMExtension extends DefaultClassManager {
override def perform(args: Array[Argument], context: Context): Unit = {
val agent = context.getAgent
- messageHistory.remove(agent)
+ historyLock.synchronized { messageHistory.remove(agent) }
}
}
diff --git a/src/main/providers/BaseHttpProvider.scala b/src/main/providers/BaseHttpProvider.scala
index c242b6f..00aa2b4 100644
--- a/src/main/providers/BaseHttpProvider.scala
+++ b/src/main/providers/BaseHttpProvider.scala
@@ -6,11 +6,39 @@ import org.nlogo.extensions.llm.models.{ChatMessage, ChatRequest, ChatResponse}
import org.nlogo.extensions.llm.config.ConfigStore
import sttp.client4._
import sttp.client4.httpclient.HttpClientFutureBackend
-import sttp.model.Uri
+import sttp.model.{StatusCode, Uri}
import ujson._
-import scala.concurrent.{Future, ExecutionContext}
+import java.util.concurrent.{Executors, ScheduledExecutorService, TimeUnit}
+import scala.concurrent.{Future, ExecutionContext, Promise}
import scala.util.{Try, Success, Failure}
+object BaseHttpProvider {
+ // Single daemon thread schedules retry attempts. Daemon so it never blocks JVM
+ // shutdown; one idle thread persists across extension reloads, which is fine.
+ private lazy val retryScheduler: ScheduledExecutorService =
+ Executors.newSingleThreadScheduledExecutor { (r: Runnable) =>
+ val t = new Thread(r, "llm-retry-scheduler")
+ t.setDaemon(true)
+ t
+ }
+
+ /**
+ * Run `f` after `delayMs`, off the caller and Future-pool threads, so backoff
+ * never blocks NetLogo's thread or starves the global execution context.
+ */
+ private[providers] def delayedFuture[A](delayMs: Long)(f: => Future[A])(
+ implicit ec: ExecutionContext
+ ): Future[A] = {
+ val p = Promise[A]()
+ retryScheduler.schedule(
+ new Runnable { def run(): Unit = p.completeWith(f) },
+ delayMs,
+ TimeUnit.MILLISECONDS
+ )
+ p.future
+ }
+}
+
/**
* Abstract base class for HTTP-based LLM providers
*
@@ -20,7 +48,15 @@ import scala.util.{Try, Success, Failure}
abstract class BaseHttpProvider(implicit ec: ExecutionContext) extends LLMProvider {
protected val configStore = new ConfigStore()
- protected val backend = HttpClientFutureBackend()
+ // lazy + overridable so tests can substitute a stub backend without ever
+ // constructing the real HTTP client.
+ protected lazy val backend: Backend[Future] = HttpClientFutureBackend()
+
+ // Retry policy for rate-limit (HTTP 429) responses. retryBaseDelayMs is a
+ // protected def so tests can shrink the delays.
+ private val MaxRetries = 3
+ private val MaxDelayMs = 10000L
+ protected def retryBaseDelayMs: Long = 1000L
// Initialize with provider-specific defaults
initializeDefaults()
@@ -119,14 +155,48 @@ abstract class BaseHttpProvider(implicit ec: ExecutionContext) extends LLMProvid
.body(requestBody)
.post(apiUrl)
- httpRequest.send(backend).map { response =>
- response.body match {
- case Right(responseBody) =>
- parseProviderResponse(responseBody, request.model)
- case Left(error) =>
- throw new RuntimeException(s"HTTP request failed: $error")
- }
+ executeWithRetry(httpRequest, request.model)
+ }
+
+ /**
+ * Send an HTTP request, retrying rate-limit (HTTP 429) responses with
+ * exponential backoff. Only rate-limit errors retry; all others fail
+ * immediately. Honors the server's Retry-After header when it asks for a
+ * longer wait than the backoff, capped so it can't exceed the request budget.
+ */
+ protected def executeWithRetry(
+ httpRequest: Request[Either[String, String]],
+ model: String
+ ): Future[ChatResponse] = {
+
+ def isRateLimited(code: StatusCode, error: String): Boolean =
+ code.code == 429 || error.toLowerCase.contains("rate_limit")
+
+ def delayFor(response: Response[?], attempt: Int): Long = {
+ val backoff = retryBaseDelayMs << attempt // 1s, 2s, 4s, ...
+ val retryAfterMs = response.header("Retry-After")
+ .flatMap(_.trim.toLongOption)
+ .map(_ * 1000L)
+ math.min(retryAfterMs.fold(backoff)(math.max(_, backoff)), MaxDelayMs)
}
+
+ def attempt(n: Int): Future[ChatResponse] =
+ httpRequest.send(backend).flatMap { response =>
+ response.body match {
+ case Right(responseBody) =>
+ Future.successful(parseProviderResponse(responseBody, model))
+ case Left(error) if isRateLimited(response.code, error) && n < MaxRetries =>
+ BaseHttpProvider.delayedFuture(delayFor(response, n))(attempt(n + 1))
+ case Left(error) if isRateLimited(response.code, error) =>
+ Future.failed(new RuntimeException(
+ s"HTTP request failed after ${MaxRetries + 1} attempts " +
+ s"(rate limited, HTTP ${response.code.code}): $error"))
+ case Left(error) =>
+ Future.failed(new RuntimeException(s"HTTP request failed: $error"))
+ }
+ }
+
+ attempt(0)
}
override def setConfig(key: String, value: String): Unit = {
diff --git a/src/main/providers/GeminiProvider.scala b/src/main/providers/GeminiProvider.scala
index 70ff5be..d44df27 100644
--- a/src/main/providers/GeminiProvider.scala
+++ b/src/main/providers/GeminiProvider.scala
@@ -58,14 +58,7 @@ class GeminiProvider(implicit ec: ExecutionContext) extends BaseHttpProvider {
.body(requestBody)
.post(apiUrl)
- httpRequest.send(backend).map { response =>
- response.body match {
- case Right(responseBody) =>
- parseProviderResponse(responseBody, request.model)
- case Left(error) =>
- throw new RuntimeException(s"HTTP request failed: $error")
- }
- }
+ executeWithRetry(httpRequest, request.model)
}
/**
diff --git a/src/test/DeterministicTestProvider.scala b/src/test/DeterministicTestProvider.scala
index 386ed87..263fcde 100644
--- a/src/test/DeterministicTestProvider.scala
+++ b/src/test/DeterministicTestProvider.scala
@@ -17,6 +17,7 @@ class DeterministicTestProvider(implicit ec: ExecutionContext) extends LLMProvid
private val firstOptionRegex = """(?m)^(.+?)$""".r
private val testRespondRegex = """__TEST_RESPOND:(.+)""".r
private val testThinkingRegex = """__TEST_THINKING:(.+)""".r
+ private val testDelayRegex = """__TEST_DELAY:(\d+):(.*)""".r.unanchored
override def chat(request: ChatRequest): Future[ChatResponse] = {
chat(request.messages).map { message =>
@@ -57,12 +58,28 @@ class DeterministicTestProvider(implicit ec: ExecutionContext) extends LLMProvid
}
}
- override def chat(messages: Seq[ChatMessage]): Future[ChatMessage] = Future.successful {
+ override def chat(messages: Seq[ChatMessage]): Future[ChatMessage] = {
val lastUserMessage = messages.reverseIterator
.find(_.role == "user")
.map(_.content)
.getOrElse("")
+ // Simulate a provider failure so failure-path history handling can be tested
+ if (lastUserMessage.contains("__TEST_FAIL")) {
+ return Future.failed(new RuntimeException("simulated provider failure"))
+ }
+
+ // Simulate latency so overlapping async calls can be tested deterministically.
+ // __TEST_DELAY:: sleeps then responds as if prompted with .
+ lastUserMessage match {
+ case testDelayRegex(ms, rest) =>
+ Future { Thread.sleep(ms.toLong) }.map(_ => respond(rest))
+ case _ =>
+ Future.successful(respond(lastUserMessage))
+ }
+ }
+
+ private def respond(lastUserMessage: String): ChatMessage = {
val content = if (lastUserMessage.contains("__TEST_RESPOND:")) {
// Return exactly the specified text
testRespondRegex.findFirstMatchIn(lastUserMessage).map(_.group(1).trim).getOrElse("")
diff --git a/src/test/RetrySpec.scala b/src/test/RetrySpec.scala
new file mode 100644
index 0000000..95bf660
--- /dev/null
+++ b/src/test/RetrySpec.scala
@@ -0,0 +1,105 @@
+// ABOUTME: Unit tests for BaseHttpProvider rate-limit retry with exponential backoff
+// ABOUTME: Uses an sttp BackendStub to script 429/200/500 responses without real HTTP
+package org.nlogo.extensions.llm.providers
+
+import org.nlogo.extensions.llm.models.{ChatRequest, ChatResponse, ChatMessage, Choice}
+import org.scalatest.funsuite.AnyFunSuite
+import sttp.client4._
+import sttp.client4.testing.{BackendStub, ResponseStub, StubBody}
+import sttp.model.{Header, StatusCode, Uri}
+import java.util.concurrent.atomic.AtomicInteger
+import scala.concurrent.{Await, Future}
+import scala.concurrent.ExecutionContext.Implicits.global
+import scala.concurrent.duration._
+
+/**
+ * Minimal concrete provider whose backend is a scripted stub. retryBaseDelayMs
+ * is shrunk to 10ms so the exponential backoff runs fast in tests.
+ */
+class StubbedProvider(stub: BackendStub[Future], counter: AtomicInteger) extends BaseHttpProvider {
+ override lazy val backend: Backend[Future] = stub
+ override protected def retryBaseDelayMs: Long = 10L
+
+ override def providerName: String = "stub"
+ override def defaultModel: String = "stub-model"
+ override protected def defaultBaseUrl: String = "http://stub.local"
+ override protected def baseUrlConfigKey: String = "stub_base_url"
+ override protected def apiKeyConfigKey: String = "stub_api_key"
+ override protected def defaultMaxTokens: String = "128"
+ override protected def requiresApiKey: Boolean = false
+
+ override protected def buildApiUrl(baseUrl: String): Uri = uri"$baseUrl/chat"
+ override protected def buildHeaders(apiKey: Option[String]): Map[String, String] =
+ Map("Content-Type" -> "application/json")
+ override protected def createProviderRequest(request: ChatRequest): ujson.Value =
+ ujson.Obj("messages" -> ujson.Arr(request.messages.map(m => ujson.Obj("content" -> m.content))*))
+ override protected def parseProviderResponse(responseBody: String, model: String): ChatResponse =
+ ChatResponse(
+ id = "stub-response",
+ created = 0L,
+ model = model,
+ choices = Array(Choice(0, ChatMessage.assistant(responseBody), "stop"))
+ )
+
+ def sendCount: Int = counter.get()
+}
+
+class RetrySpec extends AnyFunSuite {
+
+ private def request = ChatRequest(model = "stub-model", messages = Seq(ChatMessage.user("hi")))
+
+ /** Build a stub that returns the scripted responses in order, counting sends. */
+ private def stubReturning(responses: Response[StubBody]*): (BackendStub[Future], AtomicInteger) = {
+ val counter = new AtomicInteger(0)
+ val backend = BackendStub.asynchronousFuture.whenAnyRequest.thenRespond {
+ val idx = counter.getAndIncrement()
+ responses(math.min(idx, responses.length - 1))
+ }
+ (backend, counter)
+ }
+
+ private def rateLimited(retryAfter: Option[String] = None): Response[StubBody] = {
+ val headers = retryAfter.map(v => Seq(Header("Retry-After", v))).getOrElse(Seq.empty)
+ ResponseStub.adjust("rate limit exceeded", StatusCode.TooManyRequests, headers)
+ }
+ private def ok(body: String): Response[StubBody] =
+ ResponseStub.adjust(body, StatusCode.Ok)
+ private def serverError: Response[StubBody] =
+ ResponseStub.adjust("boom", StatusCode.InternalServerError)
+
+ test("retries 429 responses then succeeds") {
+ val (stub, counter) = stubReturning(rateLimited(), rateLimited(), ok("hello"))
+ val provider = new StubbedProvider(stub, counter)
+
+ val result = Await.result(provider.chat(request), 5.seconds)
+ assert(result.firstMessage.map(_.content).contains("hello"))
+ assert(counter.get() == 3)
+ }
+
+ test("fails after exhausting retries on persistent 429") {
+ val (stub, counter) = stubReturning(rateLimited(), rateLimited(), rateLimited(), rateLimited())
+ val provider = new StubbedProvider(stub, counter)
+
+ val ex = intercept[RuntimeException](Await.result(provider.chat(request), 10.seconds))
+ assert(ex.getMessage.contains("after 4 attempts"))
+ assert(ex.getMessage.contains("rate limited"))
+ assert(counter.get() == 4)
+ }
+
+ test("non-rate-limit errors fail immediately without retry") {
+ val (stub, counter) = stubReturning(serverError)
+ val provider = new StubbedProvider(stub, counter)
+
+ intercept[RuntimeException](Await.result(provider.chat(request), 5.seconds))
+ assert(counter.get() == 1)
+ }
+
+ test("honors Retry-After header and still succeeds") {
+ val (stub, counter) = stubReturning(rateLimited(retryAfter = Some("0")), ok("done"))
+ val provider = new StubbedProvider(stub, counter)
+
+ val result = Await.result(provider.chat(request), 5.seconds)
+ assert(result.firstMessage.map(_.content).contains("done"))
+ assert(counter.get() == 2)
+ }
+}
diff --git a/tests.txt b/tests.txt
index 44596b3..5cd9ab1 100644
--- a/tests.txt
+++ b/tests.txt
@@ -282,3 +282,64 @@ LLMLoadConfigRejectsUnknownProvider
O> carefully [llm:load-config "demos/test-config-bad-provider"] [set err error-message]
is-string? err => true
(position "opanai" err) != false => true
+
+LLMChatHistoryUnchangedOnFailure
+ extensions [llm]
+ globals [err]
+ O> llm:set-api-key "test-key"
+ O> llm:set-provider "openai"
+ O> llm:clear-history
+ O> llm:set-history [["user" "prior"] ["assistant" "context"]]
+ O> carefully [let __x llm:chat "__TEST_FAIL"] [set err error-message]
+ is-string? err => true
+ length llm:history => 2
+ (item 1 (item 0 llm:history)) => "prior"
+
+LLMChatWithThinkingHistoryUnchangedOnFailure
+ extensions [llm]
+ globals [err]
+ O> llm:set-api-key "test-key"
+ O> llm:set-provider "openai"
+ O> llm:clear-history
+ O> llm:set-history [["user" "prior"] ["assistant" "context"]]
+ O> carefully [let __x llm:chat-with-thinking "__TEST_FAIL"] [set err error-message]
+ is-string? err => true
+ length llm:history => 2
+ (item 1 (item 0 llm:history)) => "prior"
+
+LLMChatAsyncOverlappingPairsAtomic
+ extensions [llm]
+ globals [p1 p2 r1 r2 h]
+ O> llm:set-api-key "test-key"
+ O> llm:set-provider "openai"
+ O> llm:clear-history
+ O> set p1 llm:chat-async "__TEST_DELAY:300:slow"
+ O> set p2 llm:chat-async "fast"
+ O> set r1 (runresult p1)
+ O> set r2 (runresult p2)
+ r1 => "stub:slow"
+ r2 => "stub:fast"
+ O> set h llm:history
+ length h => 4
+ (item 0 (item 0 h)) => "user"
+ (item 0 (item 1 h)) => "assistant"
+ (item 0 (item 2 h)) => "user"
+ (item 0 (item 3 h)) => "assistant"
+ member? (item 1 (item 1 h)) ["stub:slow" "stub:fast"] => true
+ member? (item 1 (item 3 h)) ["stub:slow" "stub:fast"] => true
+
+LLMMixedSyncAsyncHistoryAtomic
+ extensions [llm]
+ globals [p1 r1 r2 h]
+ O> llm:set-api-key "test-key"
+ O> llm:set-provider "openai"
+ O> llm:clear-history
+ O> set p1 llm:chat-async "__TEST_DELAY:300:slow"
+ O> set r1 llm:chat "quick"
+ O> set r2 (runresult p1)
+ O> set h llm:history
+ length h => 4
+ (item 0 (item 0 h)) => "user"
+ (item 0 (item 1 h)) => "assistant"
+ (item 0 (item 2 h)) => "user"
+ (item 0 (item 3 h)) => "assistant"