Skip to content
Closed
162 changes: 162 additions & 0 deletions examples/wildfire.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/usr/bin/env python3
"""
Simple example demonstrating Wildfire Environment usage.

This example shows how to:
1. Connect to a Wildfire environment
2. Reset the environment
3. Take strategic actions (water, firebreak, wait)
4. Monitor fire spread and containment
5. Visualize the grid state

Usage:
# First, start the server:
python -m envs.wildfire_env.server.app

# Then run this script:
python examples/wildfire.py
"""

import sys
from pathlib import Path
import random

# Add src to path
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))

from envs.wildfire_env import WildfireEnv, WildfireAction
from envs.wildfire_env.client import render_grid


def simple_agent_strategy(obs):
"""
Simple firefighting strategy:
- Target burning cells with water if available
- Build firebreaks near fires if water is depleted
- Otherwise wait
"""
# Find burning cells
burning_cells = []
for y in range(obs.height):
for x in range(obs.width):
idx = y * obs.width + x
if obs.grid[idx] == 2: # burning
burning_cells.append((x, y))

if not burning_cells:
return WildfireAction(action="wait")

# Pick a random burning cell to target
target_x, target_y = random.choice(burning_cells)

# Use water if available, otherwise use firebreak
if obs.remaining_water > 0:
return WildfireAction(action="water", x=target_x, y=target_y)
elif obs.remaining_breaks > 0:
# Build firebreak adjacent to fire
return WildfireAction(action="break", x=target_x, y=target_y)
else:
return WildfireAction(action="wait")


def main():
"""Run a wildfire containment episode."""
# Connect to the Wildfire environment server
print("Connecting to Wildfire environment...")
print("Note: Make sure the server is running with: python -m envs.wildfire_env.server.app")

# Connect to local server
env = WildfireEnv(base_url="http://localhost:8000")

try:
# Reset the environment
print("\nResetting environment...")
result = env.reset()
obs = result.observation

print(f"\n🌲 Wildfire Containment Mission Started!")
print(f"Grid size: {obs.width}x{obs.height}")
print(f"Initial fires: {obs.burning_count}")
print(f"Wind direction: {obs.wind_dir}")
print(f"Humidity: {obs.humidity:.2f}")
print(f"Water capacity: {obs.remaining_water}")
print(f"Firebreak materials: {obs.remaining_breaks}")

# Print initial grid
print("\nInitial state:")
print(render_grid(obs))
print("\nLegend: ⬛=ash 🟩=fuel 🟥=fire 🟫=firebreak 🟦=water")

# Run episode
print("\n" + "="*60)
print("Starting containment operations...")
print("="*60)

episode_reward = 0
step_count = 0
max_steps = 50 # Limit steps for demo

while not result.done and step_count < max_steps:
# Choose action using simple strategy
action = simple_agent_strategy(obs)

# Take action
result = env.step(action)
obs = result.observation
episode_reward += result.reward or 0
step_count += 1

# Print progress every 5 steps
if step_count % 5 == 0 or result.done:
print(f"\n--- Step {step_count} ---")
print(f"Action: {action.action}" +
(f" at ({action.x}, {action.y})" if action.x is not None else ""))
print(f"Reward: {result.reward:.3f} | Total: {episode_reward:.2f}")
print(f"Fires: {obs.burning_count} | Burned: {obs.burned_count}")
print(f"Water left: {obs.remaining_water} | Breaks left: {obs.remaining_breaks}")
print(render_grid(obs))

if result.done:
break

# Episode summary
print("\n" + "="*60)
print("🏁 EPISODE COMPLETE")
print("="*60)

if obs.burning_count == 0:
print("✅ SUCCESS! All fires have been extinguished!")
else:
print(f"⚠️ Episode ended with {obs.burning_count} fires still burning")

print(f"\nFinal Statistics:")
print(f" Steps taken: {step_count}")
print(f" Total reward: {episode_reward:.2f}")
print(f" Cells burned: {obs.burned_count}")
print(f" Cells saved: {obs.width * obs.height - obs.burned_count}")
print(f" Water used: {result.observation.remaining_water} remaining (started with more)")
print(f" Firebreaks used: {result.observation.remaining_breaks} remaining")

# Get environment state
state = env.state()
print(f"\n📊 Environment State:")
print(f" Episode ID: {state.episode_id}")
print(f" Total burned: {state.total_burned}")
print(f" Total extinguished: {state.total_extinguished}")
print(f" Final wind: {state.wind_dir}")
print(f" Final humidity: {state.humidity:.2f}")

except Exception as e:
print(f"\n❌ Error: {e}")
print("\nMake sure the Wildfire server is running:")
print(" python -m envs.wildfire_env.server.app")

finally:
# Cleanup
print("\nClosing environment...")
env.close()
print("Done!")


if __name__ == "__main__":
main()
163 changes: 163 additions & 0 deletions scripts/deploy_to_hf.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#!/bin/bash

# OpenEnv Hugging Face Deployment Script for PRs
# This script deploys a new environment to Hugging Face Spaces

set -e

# Parse command line arguments
ENV_NAME=""
SPACE_SUFFIX=""
HUB_TAG="openenv"

while [[ $# -gt 0 ]]; do
case $1 in
--env)
ENV_NAME="$2"
shift 2
;;
--space-suffix)
SPACE_SUFFIX="$2"
shift 2
;;
--hub-tag)
HUB_TAG="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done

# Validate required parameters
if [ -z "$ENV_NAME" ]; then
echo "Error: --env parameter is required"
echo "Usage: $0 --env <environment_name> [--space-suffix <suffix>] [--hub-tag <tag>]"
exit 1
fi

if [ -z "$HF_TOKEN" ]; then
echo "Error: HF_TOKEN environment variable is required"
exit 1
fi

if [ -z "$HF_USERNAME" ]; then
HF_USERNAME="openenv"
echo "Using default HF_USERNAME: $HF_USERNAME"
fi

# Set space name
SPACE_NAME="${ENV_NAME}${SPACE_SUFFIX}"

echo "=========================================="
echo "Deploying $ENV_NAME to Hugging Face Space"
echo "Space name: $SPACE_NAME"
echo "Hub tag: $HUB_TAG"
echo "=========================================="

# Step 1: Prepare files using existing script
echo "Step 1: Preparing files for deployment..."
chmod +x scripts/prepare_hf_deployment.sh
./scripts/prepare_hf_deployment.sh "$ENV_NAME" ""

STAGING_DIR="hf-staging_${ENV_NAME}"

if [ ! -d "$STAGING_DIR" ]; then
echo "Error: Staging directory $STAGING_DIR not found"
exit 1
fi

# Step 2: Clone or create HF Space
echo "Step 2: Setting up Hugging Face Space..."
HF_SPACE_URL="https://${HF_USERNAME}:${HF_TOKEN}@huggingface.co/spaces/${HF_USERNAME}/${SPACE_NAME}"
HF_SPACE_DIR="hf-space-${ENV_NAME}"

rm -rf "$HF_SPACE_DIR"

if git clone "$HF_SPACE_URL" "$HF_SPACE_DIR" 2>/dev/null; then
echo "✓ Space exists, updating..."
else
echo "✓ Creating new space..."
mkdir -p "$HF_SPACE_DIR"
cd "$HF_SPACE_DIR"
git init
git remote add origin "$HF_SPACE_URL"
cd ..
fi

# Step 3: Copy prepared files
echo "Step 3: Copying files to space..."
cd "$HF_SPACE_DIR"

# Clear existing files (except .git)
find . -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +

# Copy all prepared files
cp -r "../${STAGING_DIR}"/* .

# Create README.md if it doesn't exist
if [ ! -f "README.md" ]; then
cat > README.md << 'EOF'
---
title: OpenEnv Environment
emoji: 🤖
colorFrom: blue
colorTo: green
sdk: docker
pinned: false
---

# OpenEnv Environment

This is an environment from the [OpenEnv](https://github.com/meta-pytorch/OpenEnv) framework.

## Usage

This space provides an HTTP API for interacting with the environment. See the OpenEnv documentation for details.
EOF
fi

# Step 4: Commit and push
echo "Step 4: Deploying to Hugging Face..."

git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"

if [ -n "$(git status --porcelain)" ]; then
git add .
git commit -m "🤖 Deploy $ENV_NAME environment - $(date +'%Y-%m-%d %H:%M:%S')

Deployed from PR
Environment: $ENV_NAME
Tag: $HUB_TAG"

echo "Pushing to Hugging Face..."

# Try to push to main first, then master as fallback
if git push origin main 2>/dev/null; then
echo "✅ Successfully deployed to https://huggingface.co/spaces/$HF_USERNAME/$SPACE_NAME"
elif git push origin master 2>/dev/null; then
echo "✅ Successfully deployed to https://huggingface.co/spaces/$HF_USERNAME/$SPACE_NAME"
else
echo "❌ Failed to push to Hugging Face"
cd ..
rm -rf "$HF_SPACE_DIR"
rm -rf "$STAGING_DIR"
exit 1
fi
else
echo "ℹ️ No changes to deploy"
fi

# Step 5: Cleanup
cd ..
echo "Step 5: Cleaning up..."
rm -rf "$HF_SPACE_DIR"
rm -rf "$STAGING_DIR"

echo "=========================================="
echo "✅ Deployment complete!"
echo "Space URL: https://huggingface.co/spaces/$HF_USERNAME/$SPACE_NAME"
echo "=========================================="
48 changes: 48 additions & 0 deletions src/.ipynb_checkpoints/test-checkpoint.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "a7146315",
"metadata": {
"vscode": {
"languageId": "plaintext"
}
},
"outputs": [],
"source": [
"from envs.wildfire_env import WildfireEnv, WildfireAction\n",
"\n",
"env = WildfireEnv(base_url=\"http://localhost:8020\")\n",
"result = env.reset()\n",
"print(\"🔥 Fires:\", result.observation.burning_count)\n",
"print(\"💧 Water:\", result.observation.remaining_water)\n",
"\n",
"for t in range(3):\n",
" action = WildfireAction(action=\"wait\")\n",
" result = env.step(action)\n",
" print(f\"Step {t}: reward={result.reward:.2f}, done={result.done}\")\n",
"env.close()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2451db4d",
"metadata": {
"vscode": {
"languageId": "plaintext"
}
},
"outputs": [],
"source": []
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
9 changes: 9 additions & 0 deletions src/envs/disease_control_env/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .models import DiseaseAction, DiseaseObservation, DiseaseState
from .client import DiseaseControlEnv

__all__ = [
"DiseaseAction",
"DiseaseObservation",
"DiseaseState",
"DiseaseControlEnv",
]
Loading
Loading