Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Medieval Village AI System - Three.js Visualization</title> | |
| <script async src="https://unpkg.com/es-module-shims@1.8.0/dist/es-module-shims.js"></script> | |
| <style> | |
| body { | |
| margin: 0; | |
| padding: 0; | |
| font-family: Arial, sans-serif; | |
| background-color: #2c3e50; | |
| color: white; | |
| overflow: hidden; | |
| } | |
| #container { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| #ui-panel { | |
| position: absolute; | |
| top: 20px; | |
| left: 20px; | |
| background: rgba(0, 0, 0, 0.8); | |
| padding: 10px; | |
| border-radius: 10px; | |
| min-width: 200px; | |
| max-width: 250px; | |
| height: calc(100vh - 40px); | |
| overflow-y: auto; | |
| z-index: 101; | |
| } | |
| #stats-panel { | |
| position: absolute; | |
| top: 20px; | |
| right: 20px; | |
| background: rgba(0, 0, 0, 0.8); | |
| padding: 20px; | |
| border-radius: 10px; | |
| min-width: 200px; | |
| z-index: 100; | |
| } | |
| #villager-info { | |
| position: absolute; | |
| bottom: 20px; | |
| right: 20px; | |
| background: rgba(0, 0, 0, 0.8); | |
| padding: 20px; | |
| border-radius: 10px; | |
| min-width: 300px; | |
| max-height: 200px; | |
| overflow-y: auto; | |
| z-index: 100; | |
| } | |
| .control-group { | |
| margin-bottom: 8px; | |
| } | |
| .control-group label { | |
| font-size: 12px; | |
| } | |
| .control-group input, .control-group button { | |
| padding: 3px; | |
| font-size: 10px; | |
| } | |
| .control-group h4 { | |
| font-size: 14px; | |
| margin: 8px 0 4px 0; | |
| } | |
| .control-group button { | |
| background-color: #3498db; | |
| color: white; | |
| cursor: pointer; | |
| transition: background-color 0.3s; | |
| border: none; | |
| border-radius: 3px; | |
| } | |
| .control-group button:hover { | |
| background-color: #2980b9; | |
| } | |
| .weather-btn, .animal-btn, .warrior-btn { | |
| background-color: #3498db; | |
| color: white; | |
| cursor: pointer; | |
| transition: background-color 0.3s; | |
| margin: 1px; | |
| padding: 2px; | |
| font-size: 12px; | |
| width: 30px; | |
| height: 30px; | |
| display: inline-block; | |
| } | |
| .disaster-btn { | |
| background-color: #e74c3c; | |
| color: white; | |
| cursor: pointer; | |
| transition: background-color 0.3s; | |
| margin: 1px; | |
| padding: 2px; | |
| font-size: 12px; | |
| width: 30px; | |
| height: 30px; | |
| display: inline-block; | |
| } | |
| .weather-btn:hover, .disaster-btn:hover, .animal-btn:hover, .warrior-btn:hover { | |
| background-color: #2980b9; | |
| } | |
| .disaster-btn { | |
| background-color: #e74c3c; | |
| } | |
| .disaster-btn:hover { | |
| background-color: #c0392b; | |
| } | |
| .animal-btn { | |
| background-color: #27ae60; | |
| } | |
| .animal-btn:hover { | |
| background-color: #229954; | |
| } | |
| .warrior-btn { | |
| background-color: #f39c12; | |
| } | |
| .warrior-btn:hover { | |
| background-color: #d68910; | |
| } | |
| .villager-item { | |
| padding: 10px; | |
| margin-bottom: 10px; | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: 5px; | |
| cursor: pointer; | |
| transition: background-color 0.3s; | |
| } | |
| .villager-item:hover { | |
| background: rgba(255, 255, 255, 0.2); | |
| } | |
| .villager-item.selected { | |
| background: rgba(52, 152, 219, 0.3); | |
| border: 2px solid #3498db; | |
| } | |
| .state-indicator { | |
| display: inline-block; | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| margin-right: 8px; | |
| } | |
| .state-sleep { background-color: #7f8c8d; } | |
| .state-work { background-color: #e74c3c; } | |
| .state-eat { background-color: #f39c12; } | |
| .state-socialize { background-color: #9b59b6; } | |
| .state-idle { background-color: #95a5a6; } | |
| #instructions { | |
| position: absolute; | |
| bottom: 250px; | |
| right: 20px; | |
| background: rgba(0, 0, 0, 0.8); | |
| padding: 15px; | |
| border-radius: 10px; | |
| max-width: 300px; | |
| font-size: 12px; | |
| z-index: 100; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="container"></div> | |
| <!-- UI Controls Panel --> | |
| <div id="ui-panel"> | |
| <h3>Village Controls</h3> | |
| <div class="control-group"> | |
| <label for="villager-count">Villager Count: <span id="villager-count-display">0</span></label> | |
| </div> | |
| <div class="control-group"> | |
| <label for="add-villager-btn">Add Villager</label> | |
| <button id="add-villager-btn" title="Add New Villager">👨🌾</button> | |
| </div> | |
| <div class="control-group"> | |
| <label for="reset-btn">Reset Simulation</label> | |
| <button id="reset-btn" title="Reset All">🔄</button> | |
| </div> | |
| <div class="control-group"> | |
| <label for="time-speed">Time Speed: <span id="time-speed-display">1.0x</span></label> | |
| <input type="range" id="time-speed" min="0.1" max="5" step="0.1" value="1.0"> | |
| </div> | |
| <div class="control-group"> | |
| <label for="show-paths">Show Movement Paths</label> | |
| <input type="checkbox" id="show-paths" checked> | |
| </div> | |
| <div class="control-group"> | |
| <label for="show-titles">Show Villager Titles</label> | |
| <input type="checkbox" id="show-titles" checked> | |
| </div> | |
| <!-- Weather Controls --> | |
| <div class="control-group"> | |
| <h4>Weather Controls</h4> | |
| </div> | |
| <div class="control-group"> | |
| <label for="fog-control">Fog Intensity</label> | |
| <input type="range" id="fog-control" min="0" max="100" value="50"> | |
| </div> | |
| <div class="control-group"> | |
| <button id="weather-sun" class="weather-btn" title="Sunny Weather">☀️</button> | |
| <button id="weather-rain" class="weather-btn" title="Rain Weather">🌧️</button> | |
| <button id="weather-snow" class="weather-btn" title="Snow Weather">❄️</button> | |
| </div> | |
| <!-- Disaster Controls --> | |
| <div class="control-group"> | |
| <h4>Disaster Controls</h4> | |
| </div> | |
| <div class="control-group"> | |
| <button id="disaster-fire" class="disaster-btn" title="Fire Disaster">🔥</button> | |
| <button id="disaster-hurricane" class="disaster-btn" title="Hurricane Disaster">🌪️</button> | |
| <button id="disaster-flood" class="disaster-btn" title="Flood Disaster">🌊</button> | |
| <button id="disaster-earthquake" class="disaster-btn" title="Earthquake Disaster">🌍</button> | |
| <button id="disaster-plague" class="disaster-btn" title="Plague Disaster">🦠</button> | |
| </div> | |
| <!-- Animal/Beast Controls --> | |
| <div class="control-group"> | |
| <h4>Animal/Beast Controls</h4> | |
| </div> | |
| <div class="control-group"> | |
| <button id="spawn-wolf" class="animal-btn" title="Spawn Wolf">🐺</button> | |
| <button id="spawn-bear" class="animal-btn" title="Spawn Bear">🐻</button> | |
| <button id="spawn-dragon" class="animal-btn" title="Spawn Dragon">🐉</button> | |
| </div> | |
| <!-- Warrior Controls --> | |
| <div class="control-group"> | |
| <h4>Warrior Controls</h4> | |
| </div> | |
| <div class="control-group"> | |
| <button id="add-warrior" class="warrior-btn" title="Add Warrior">⚔️</button> | |
| <button id="dispatch-warriors" class="warrior-btn" title="Dispatch Warriors">🛡️</button> | |
| </div> | |
| <!-- LLM Controls --> | |
| <div class="control-group"> | |
| <h4>LLM Controls <span id="llm-status-indicator" style="width: 10px; height: 10px; border-radius: 50%; display: inline-block; margin-left: 10px;"></span></h4> | |
| </div> | |
| <div class="control-group"> | |
| <label for="llm-model">Select LLM Model:</label> | |
| <select id="llm-model" style="width: 100%; padding: 2px; font-size: 11px;"> | |
| <option value="meta-llama/Llama-3.1-8B-Instruct">Llama-3.1-8B-Instruct</option> | |
| <option value="google/gemma-3-270m-it">Gemma-3-270m-it</option> | |
| <option value="google/gemma-3-4b-it">Gemma-3-4b-it</option> | |
| <option value="google/gemma-3-27b-it">Gemma-3-27b-it</option> | |
| <option value="Qwen/Qwen3-4B-Instruct-2507">Qwen3-4B-Instruct</option> | |
| <option value="Qwen/Qwen3-8B">Qwen3-8B</option> | |
| <option value="mistralai/Mistral-7B-Instruct-v0.3">Mistral-7B-Instruct</option> | |
| <option value="HuggingFaceH4/zephyr-7b-beta">Zephyr-7b-beta</option> | |
| <option value="TinyLlama/TinyLlama-1.1B-Chat-v1.0">TinyLlama-1.1B-Chat</option> | |
| <option value="microsoft/Phi-3-mini-4k-instruct">Phi-3-mini-4k</option> | |
| <option value="stabilityai/stablelm-2-1_6b">StableLM-2-1_6b</option> | |
| <option value="NousResearch/Hermes-2-Pro-Llama-3-8B">Hermes-2-Pro-Llama-3</option> | |
| <option value="CohereForAI/c4ai-command-r-v01">C4AI-Command-R</option> | |
| <option value="nvidia/Nemotron-Research-Reasoning-Qwen-1.5B">Nemotron-Qwen-1.5B</option> | |
| <option value="inclusionAI/AReaL-boba-2-8B">AReaL-boba-2-8B</option> | |
| </select> | |
| </div> | |
| <div class="control-group"> | |
| <label for="llm-query">Ask the LLM:</label> | |
| <input type="text" id="llm-query" placeholder="Enter your question..." style="width: 100%; padding: 2px; font-size: 11px;"> | |
| </div> | |
| <div class="control-group"> | |
| <button id="llm-submit" style="width: 100%; padding: 3px; font-size: 11px;">Submit Query</button> | |
| </div> | |
| <div class="control-group"> | |
| <label for="llm-response">LLM Response:</label> | |
| <div id="llm-response" style="background: rgba(255, 255, 255, 0.1); padding: 5px; border-radius: 5px; min-height: 50px; max-height: 100px; overflow-y: auto; font-size: 11px;"> | |
| No response yet. Submit a query to get started. | |
| </div> | |
| </div> | |
| <div class="control-group"> | |
| <div style="background: rgba(255, 255, 0, 0.1); padding: 5px; border-radius: 5px; font-size: 9px; margin-top: 5px;"> | |
| <strong>API Token Required:</strong> To use the LLM functionality, you need to set your Hugging Face API token. | |
| Get one from <a href="https://huggingface.co/settings/tokens" target="_blank" style="color: #3498db;">Hugging Face</a>. | |
| <br><br> | |
| If running this application with a server that has access to the HF_TOKEN environment variable, the token will be automatically used. | |
| <br><br> | |
| For manual setup, you can set the token in the browser console with: | |
| <code>window.HF_TOKEN = 'your-actual-token-here'</code> | |
| <br>or<br> | |
| <code>app.llmHandler.setApiToken('your-actual-token-here')</code> | |
| <br><br> | |
| Check the browser console for debugging information about the token status. | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Stats Panel --> | |
| <div id="stats-panel"> | |
| <h3>Simulation Stats</h3> | |
| <div id="stats-content"> | |
| <div>Time: <span id="game-time">0:00</span></div> | |
| <div>FPS: <span id="fps">0</span></div> | |
| <div>Villagers: <span id="villager-count-stat">0</span></div> | |
| <div>Buildings: <span id="building-count">0</span></div> | |
| <div>Resources: <span id="resource-count">0</span></div> | |
| </div> | |
| </div> | |
| <!-- Villager Information Panel --> | |
| <div id="villager-info"> | |
| <h3>Villager Information</h3> | |
| <div id="villager-list"> | |
| <p>No villagers selected</p> | |
| </div> | |
| </div> | |
| <!-- Instructions Panel --> | |
| <div id="instructions"> | |
| <h4>Controls:</h4> | |
| <ul> | |
| <li><strong>Mouse:</strong> Look around</li> | |
| <li><strong>WASD:</strong> Move camera</li> | |
| <li><strong>Space:</strong> Up</li> | |
| <li><strong>Shift:</strong> Down</li> | |
| <li><strong>Click villager:</strong> Select for info</li> | |
| </ul> | |
| <h4>Legend:</h4> | |
| <ul> | |
| <li><span class="state-indicator state-sleep"></span>Sleep</li> | |
| <li><span class="state-indicator state-work"></span>Work</li> | |
| <li><span class="state-indicator state-eat"></span>Eat</li> | |
| <li><span class="state-indicator state-socialize"></span>Socialize</li> | |
| </ul> | |
| </div> | |
| <!-- Hugging Face Token --> | |
| <script> | |
| // In a server-side implementation, the HF_TOKEN environment variable would be injected here | |
| // For example, a Node.js server could inject it like this: | |
| // window.HF_TOKEN = process.env.HF_TOKEN; | |
| // | |
| // For client-side usage, users can set the token in the browser console: | |
| // window.HF_TOKEN = "your-actual-hugging-face-token"; | |
| // | |
| // For testing purposes, you can uncomment the line below and replace with your actual token: | |
| // window.HF_TOKEN = "your-actual-hugging-face-token"; | |
| window.HF_TOKEN = null; | |
| </script> | |
| <!-- Three.js and Application Scripts --> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js?v=1"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js?v=1"></script> | |
| <script type="module" src="app_new.js?v=1"></script> | |
| </body> | |
| </html> |