๐ฒ Wildfire Environment#
Autonomous wildfire-control simulation for reinforcement-learning agents, built on the OpenEnv framework. Agents must contain spreading fires using water, firebreaks, and timing strategies under changing wind and humidity conditions.
๐ Table of Contents#
๐ฅ Why Wildfire Simulation?#
Wildland fires are intensifying globally due to climate change โ increasing the urgency for AI-assisted decision-making. This environment explores how intelligent systems can control fire spread in real time, under limited resources.
Research Motivation#
โ Based on real wildfire science inspired by:
Rothermel Surface Fire Spread Model (USDA Forest Service)
MITRE Firelineโs SimFire โ physics-informed RL fire simulator
SimHarness โ RL evaluation for disaster response
Application Goals#
Research Theme |
Role in This Environment |
|---|---|
Resource-Constrained Planning |
Finite water + firebreak budgets |
Fire Spread + Containment Strategy |
Directional wind & moisture effects |
Disaster Response RL |
Safety-focused reward design |
LLM Agents for Control Tasks |
Text-based action decision making |
This makes WildfireEnv a fast, controllable, and open benchmark for applied RL and LLM reasoning.
๐ Quick Start#
Using Docker (Recommended)#
# Build base image (first time only)
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
# Build wildfire environment
docker build -t wildfire-env:latest -f envs/wildfire_env/server/Dockerfile .
# Run container
docker run -p 8000:8000 -e ENABLE_WEB_INTERFACE=true wildfire-env:latest
Note: The web interface can be enabled with ENABLE_WEB_INTERFACE=true. Access it at http://localhost:8000/web when enabled.
Basic Python Client#
from envs.wildfire_env import WildfireEnv, WildfireAction
# Connect to running server
env = WildfireEnv(base_url="http://localhost:8000")
# Reset environment
result = env.reset()
obs = result.observation
print(f"Grid: {obs.width}x{obs.height}, Fires: {obs.burning_count}, Water: {obs.remaining_water}")
# Take action (water a burning cell)
result = env.step(WildfireAction(action="water", x=10, y=15))
print(f"Reward: {result.reward:.2f}, Burning: {result.observation.burning_count}")
# Create firebreak
result = env.step(WildfireAction(action="break", x=12, y=15))
# Wait (fire spreads)
result = env.step(WildfireAction(action="wait"))
env.close()
๐ฅ Environment Overview#
This environment models forest-fire dynamics influenced by:
Wind direction (8 directions + calm) - accelerates fire spread in wind direction
Humidity (0.0-1.0) - suppresses ignition probability
Fuel type and spread rate - vegetation burns and spreads to neighbors
Limited resources (water units, break materials) - strategic resource management
Time pressure (each step costs small reward penalty)
The goal is to minimize fire spread and total burned area while using resources efficiently.
Episode Termination#
An episode ends when:
All fires are extinguished (
burning_count == 0) - Success!Maximum steps reached (
step_count >= max_steps) - Time limit exceeded
๐งฑ Grid Format & Encoding#
Grid Structure#
The grid is returned as a flat 1D array in the observation. To access cell at position (x, y):
index = y * width + x
cell_value = observation.grid[index]
Example: For a 32ร32 grid, cell at (10, 15):
index = 15 * 32 + 10 # = 490
cell_value = observation.grid[490]
Cell Encoding#
Code |
Meaning |
Color (Visualization) |
Behavior |
|---|---|---|---|
|
Ash (burned) |
Black โซ |
Burned out, cannot reignite |
|
Fuel |
Green ๐ฉ |
Healthy vegetation, can ignite |
|
Burning |
Red ๐ฅ |
Currently on fire, spreads to neighbors |
|
Firebreak |
Brown ๐ซ |
Barrier, fire cannot cross |
|
Water/Damp |
Blue ๐ต |
Dampened, immune to ignition temporarily |
Grid Visualization Example#
import numpy as np
obs = env.reset().observation
grid_2d = np.array(obs.grid).reshape(obs.height, obs.width)
# Now grid_2d[y][x] gives the cell value at position (x, y)
print(grid_2d[15][10]) # Cell at x=10, y=15
๐ฎ Actions#
Action Types#
1. water - Apply Water#
Extinguishes burning cells and dampens fuel to prevent ignition.
WildfireAction(action="water", x=10, y=15)
Effects:
Burning cell (2): Extinguishes โ becomes Water/Damp (4), gives +0.25 reward
Fuel cell (1): Dampens โ becomes Water/Damp (4), gives -0.10 reward (preventive, slight penalty)
Water/Damp cell (4): Redundant watering, gives -0.05 reward
Ash/Break (0, 3): Wasteful, gives -0.05 reward
Resource Cost: 1 water unit per action
Requires: remaining_water > 0 and valid coordinates
Best Use: Extinguish active fires before they spread
2. break - Create Firebreak#
Builds a fire-resistant barrier that stops fire spread.
WildfireAction(action="break", x=12, y=15)
Effects:
Fuel/Water cell (1, 4): Creates firebreak โ becomes Firebreak (3), gives +0.15 reward
Burning cell (2): Extinguishes โ becomes Firebreak (3), gives -0.02 reward (less effective than water)
Firebreak (3): Redundant, gives -0.01 reward
Ash (0): Wasteful, gives -0.02 reward
Resource Cost: 1 firebreak material per action
Requires: remaining_breaks > 0 and valid coordinates
Best Use: Create barriers ahead of fire front to contain spread
3. wait - Do Nothing#
Let natural fire dynamics occur (fire spreads).
WildfireAction(action="wait")
Effects:
No resource cost
No coordinate required
Fire spreads naturally to neighboring cells
Small time penalty (-0.01 reward per step)
Best Use: When fire is contained, waiting for it to burn out
Invalid Actions#
Actions that fail (give -0.05 reward):
Invalid coordinates (out of bounds)
Using water when
remaining_water == 0Using break when
remaining_breaks == 0Missing required coordinates for water/break actions
๐๏ธ Observations#
WildfireObservation#
Returned after every reset() or step():
@dataclass
class WildfireObservation(Observation):
grid: List[int] # Flat array: [1,1,2,1,...] length = width ร height
width: int # Grid width (default: 32)
height: int # Grid height (default: 32)
step: int # Current step number (0 at reset)
wind_dir: str # "N", "NE", "E", "SE", "S", "SW", "W", "NW", "CALM"
humidity: float # [0.0, 1.0] - higher = less fire spread
burning_count: int # Number of cells currently on fire
burned_count: int # Total number of ash cells (cumulative)
remaining_water: int # Water units left
remaining_breaks: int # Firebreak materials left
reward_hint: float # Shaping reward (for debugging)
done: bool # Episode ended?
reward: float # Step reward
Example Observation#
result = env.reset()
obs = result.observation
print(f"Step: {obs.step}") # 0
print(f"Grid size: {obs.width}x{obs.height}") # 32x32
print(f"Grid cells: {len(obs.grid)}") # 1024
print(f"Active fires: {obs.burning_count}") # 2
print(f"Wind: {obs.wind_dir}") # "NE"
print(f"Humidity: {obs.humidity:.2f}") # 0.24
print(f"Water left: {obs.remaining_water}") # 8
print(f"Breaks left: {obs.remaining_breaks}") # 50
๐ฐ Reward Structure#
Step Rewards#
Action |
Condition |
Reward |
|---|---|---|
Water burning cell |
Extinguishes fire |
+0.25 |
Water fuel cell |
Preventive dampening |
-0.10 |
Create firebreak |
From fuel/water |
+0.15 |
Fire spreads |
Each new burning cell |
-0.15 per cell |
Fire shrinks |
Each extinguished cell |
+0.10 per cell |
New burned area |
Each cell turns to ash |
-0.05 per cell |
Time penalty |
Every step |
-0.01 |
Invalid action |
Out of bounds, no resources |
-0.05 |
Redundant action |
Watering already damp cell |
-0.05 |
Episode End Bonuses#
When episode terminates (done == True):
Fire contained (
burning_count == 0):+0.5 base bonus
+0.5 ร saved_ratio bonus (proportion of cells not burned)
Fallback reward:
+0.2 ร (1.0 - burned_ratio) bonus
Example: Perfect containment (no burned cells):
Reward = +0.5 + 0.5 ร 1.0 = +1.0
Reward Interpretation#
Positive rewards: Good containment actions, extinguishing fires
Negative rewards: Fire spread, resource waste, time penalty
Goal: Maximize cumulative reward = minimize fire damage
๐ช๏ธ Fire Spread Mechanics#
Spread Model#
Fire spreads using an 8-directional neighbor model:
Burning cells persist for
burn_lifetime = 3ticks before turning to ashEach burning cell can ignite neighboring fuel cells (8 directions)
Spread probability depends on:
Base ignition probability:
0.30(30% chance)Humidity factor:
(1.0 - humidity)- higher humidity = less spreadWind multiplier:
+2.0x in wind direction
+0.5x against wind
+1.0x perpendicular
Diagonal factor:
0.6xfor diagonal neighbors (slower spread)
Water/Damp cells (4) are immune to ignition while damp
Firebreaks (3) cannot be crossed by fire
Ash cells (0) cannot reignite
Wind Effects#
Wind Direction |
Effect on Fire Spread |
|---|---|
In wind direction |
2ร faster ignition probability |
Against wind |
0.5ร slower ignition probability |
Perpendicular |
Normal (1ร) ignition probability |
CALM |
No directional bias |
Water Dampening Duration#
Watered cells (4) remain damp for 6 ticks before reverting to fuel (1).
Example Fire Spread#
Step 0: Step 1: Step 2:
๐ฉ๐ฉ๐ฉ ๐ฉ๐ฅ๐ฉ ๐ซ๐ฅ๐ซ
๐ฉ๐ฅ๐ฉ โ ๐ฅ๐ฅ๐ฅ โ ๐ฅ๐ฅ๐ฅ (Wind: E, spreading east)
๐ฉ๐ฉ๐ฉ ๐ฉ๐ฅ๐ฉ ๐ซ๐ฅ๐ซ
โ๏ธ Configuration#
Environment Variables#
Set these before starting the server:
Variable |
Description |
Default |
Range |
|---|---|---|---|
|
Grid width in cells |
|
8-128 |
|
Grid height in cells |
|
8-128 |
|
Initial humidity level |
|
0.0-1.0 |
|
Wind direction (fixed) |
Random |
|
|
Random seed |
|
Any integer |
|
Max steps per episode |
|
10-1000 |
|
Initial water units |
|
1-100 |
|
Initial firebreak materials |
|
1-200 |
Python API Configuration#
from envs.wildfire_env.server.wildfire_environment import WildfireEnvironment
env = WildfireEnvironment(
width=64,
height=64,
humidity=0.3,
init_sources=3, # Number of initial fires
max_steps=200,
water_capacity=10,
break_capacity=75,
seed=42
)
Docker Configuration#
docker run -p 8000:8000 \
-e WILDFIRE_WIDTH=64 \
-e WILDFIRE_HEIGHT=64 \
-e WILDFIRE_HUMIDITY=0.4 \
-e WILDFIRE_WIND=N \
-e WILDFIRE_WATER_CAPACITY=12 \
wildfire-env:latest
Custom Configuration#
# Build and run with custom configuration
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
docker build -t wildfire-env:latest -f envs/wildfire_env/server/Dockerfile .
docker run -p 8000:8000 \
-e ENABLE_WEB_INTERFACE=true \
-e WILDFIRE_WIDTH=64 \
-e WILDFIRE_HEIGHT=64 \
-e WILDFIRE_HUMIDITY=0.5 \
wildfire-env:latest
๐ Installation & Usage#
Option 1: Docker (Recommended)#
Manual setup:
# Build base image (first time only)
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
# Build wildfire environment
docker build -t wildfire-env:latest -f envs/wildfire_env/server/Dockerfile .
# Run container
docker run -p 8000:8000 -e ENABLE_WEB_INTERFACE=true wildfire-env:latest
This approach:
Builds the base image if needed
Rebuilds the wildfire image
Starts the container
Shows logs in real-time
Alternative: Using build_docker.sh script:
# Build base image (first time only)
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
# Build wildfire environment using the script
cd src/envs/wildfire_env/server
./build_docker.sh
# Run container
docker run -d -p 8000:8000 --name wildfire-env-container wildfire-env:latest
# View logs
docker logs -f wildfire-env-container
# Stop container
docker stop wildfire-env-container
# Remove container
docker rm wildfire-env-container
Option 2: Local Development (No Docker)#
Requirements:
pip install fastapi uvicorn numpy matplotlib requests
Run server:
# From OpenEnv root directory
python -m envs.wildfire_env.server.app
Or with environment variables:
WILDFIRE_WIDTH=64 WILDFIRE_HUMIDITY=0.3 python -m envs.wildfire_env.server.app
๐ API Reference#
Client Class#
from envs.wildfire_env import WildfireEnv
# Connect to existing server
env = WildfireEnv(base_url="http://localhost:8000")
# Or create from Docker image
env = WildfireEnv.from_docker_image("wildfire-env:latest")
Methods#
reset() -> StepResult[WildfireObservation]#
Resets the environment to initial state.
result = env.reset()
obs = result.observation
print(f"New episode: {obs.step == 0}")
step(action: WildfireAction) -> StepResult[WildfireObservation]#
Takes an action and returns new observation.
action = WildfireAction(action="water", x=10, y=15)
result = env.step(action)
print(f"Reward: {result.reward}, Done: {result.done}")
state -> WildfireState#
Access current environment state.
state = env.state
print(f"Episode ID: {state.episode_id}")
print(f"Total burned: {state.total_burned}")
print(f"Total extinguished: {state.total_extinguished}")
close()#
Closes the connection (for HTTP clients, this is a no-op but good practice).
env.close()
Data Classes#
WildfireAction#
@dataclass
class WildfireAction(Action):
action: str # "water" | "break" | "wait"
x: Optional[int] = None # Target X coordinate (required for water/break)
y: Optional[int] = None # Target Y coordinate (required for water/break)
Examples:
WildfireAction(action="water", x=10, y=15)
WildfireAction(action="break", x=12, y=15)
WildfireAction(action="wait") # x, y not needed
WildfireObservation#
See Observations section for full details.
WildfireState#
@dataclass
class WildfireState(State):
episode_id: str
step_count: int
total_burned: int
total_extinguished: int
last_action: str
width: int
height: int
wind_dir: str
humidity: float
remaining_water: int
remaining_breaks: int
grid: List[int]
burn_timers: List[int]
๐ Examples#
Example 1: Simple Containment Strategy#
from envs.wildfire_env import WildfireEnv, WildfireAction
import numpy as np
env = WildfireEnv(base_url="http://localhost:8000")
result = env.reset()
obs = result.observation
grid_2d = np.array(obs.grid).reshape(obs.height, obs.width)
total_reward = 0
while not result.done:
# Find burning cells
burning_indices = np.where(grid_2d == 2)
if len(burning_indices[0]) > 0 and obs.remaining_water > 0:
# Water the first burning cell
y, x = burning_indices[0][0], burning_indices[1][0]
action = WildfireAction(action="water", x=int(x), y=int(y))
else:
# Wait if no water or no fires
action = WildfireAction(action="wait")
result = env.step(action)
obs = result.observation
total_reward += result.reward or 0
# Update grid
grid_2d = np.array(obs.grid).reshape(obs.height, obs.width)
print(f"Step {obs.step}: Burning={obs.burning_count}, Reward={result.reward:.3f}")
print(f"\nEpisode ended. Total reward: {total_reward:.2f}")
print(f"Final stats: Burned={obs.burned_count}, Extinguished={env.state.total_extinguished}")
env.close()
Example 2: Firebreak Strategy#
from envs.wildfire_env import WildfireEnv, WildfireAction
import numpy as np
env = WildfireEnv(base_url="http://localhost:8000")
result = env.reset()
obs = result.observation
def create_firebreak_barrier(obs, env):
"""Create firebreak ahead of fire front based on wind direction."""
grid_2d = np.array(obs.grid).reshape(obs.height, obs.width)
wind = obs.wind_dir
# Find burning cells
burning_y, burning_x = np.where(grid_2d == 2)
if len(burning_x) == 0 or obs.remaining_breaks == 0:
return WildfireAction(action="wait")
# Calculate fire front position
if wind == "E":
target_x = int(np.max(burning_x)) + 2 # Ahead of easternmost fire
target_y = int(np.mean(burning_y))
elif wind == "W":
target_x = int(np.min(burning_x)) - 2
target_y = int(np.mean(burning_y))
elif wind == "N":
target_x = int(np.mean(burning_x))
target_y = int(np.min(burning_y)) - 2
elif wind == "S":
target_x = int(np.mean(burning_x))
target_y = int(np.max(burning_y)) + 2
else:
# Fallback: water nearest burning cell
return WildfireAction(action="water", x=int(burning_x[0]), y=int(burning_y[0]))
# Ensure within bounds
target_x = max(0, min(obs.width - 1, target_x))
target_y = max(0, min(obs.height - 1, target_y))
return WildfireAction(action="break", x=target_x, y=target_y)
total_reward = 0
while not result.done:
action = create_firebreak_barrier(obs, env)
result = env.step(action)
obs = result.observation
total_reward += result.reward or 0
if obs.step % 10 == 0:
print(f"Step {obs.step}: Fires={obs.burning_count}, Water={obs.remaining_water}, Breaks={obs.remaining_breaks}")
env.close()
Example 3: Visualization with Matplotlib#
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as mcolors
from envs.wildfire_env import WildfireEnv, WildfireAction
env = WildfireEnv(base_url="http://localhost:8000")
result = env.reset()
obs = result.observation
# Setup colormap
cmap = mcolors.ListedColormap([
"black", # 0 = ash
"green", # 1 = fuel
"red", # 2 = burning
"saddlebrown", # 3 = firebreak
"blue" # 4 = water
])
norm = mcolors.BoundaryNorm([0, 1, 2, 3, 4, 5], cmap.N)
fig, ax = plt.subplots(figsize=(8, 8))
plt.ion()
for step in range(50):
if result.done:
break
# Render grid
grid_2d = np.array(obs.grid).reshape(obs.height, obs.width)
ax.clear()
ax.imshow(grid_2d, cmap=cmap, norm=norm, interpolation='nearest')
ax.set_title(
f"Step {obs.step} | Fires: {obs.burning_count} | Burned: {obs.burned_count}\n"
f"Wind: {obs.wind_dir} | Humidity: {obs.humidity:.2f} | "
f"Water: {obs.remaining_water} | Breaks: {obs.remaining_breaks}"
)
plt.pause(0.1)
# Take action (simple: water first burning cell)
if obs.burning_count > 0 and obs.remaining_water > 0:
burning_indices = np.where(grid_2d == 2)
if len(burning_indices[0]) > 0:
y, x = burning_indices[0][0], burning_indices[1][0]
action = WildfireAction(action="water", x=int(x), y=int(y))
else:
action = WildfireAction(action="wait")
else:
action = WildfireAction(action="wait")
result = env.step(action)
obs = result.observation
plt.ioff()
plt.show()
env.close()
Example 4: Training Loop for RL#
from envs.wildfire_env import WildfireEnv, WildfireAction
import random
env = WildfireEnv(base_url="http://localhost:8000")
num_episodes = 10
episode_rewards = []
for episode in range(num_episodes):
result = env.reset()
obs = result.observation
episode_reward = 0
episode_steps = 0
while not result.done:
# Random policy (replace with your RL agent)
if random.random() < 0.4 and obs.remaining_water > 0:
action = WildfireAction(
action="water",
x=random.randint(0, obs.width - 1),
y=random.randint(0, obs.height - 1)
)
elif random.random() < 0.3 and obs.remaining_breaks > 0:
action = WildfireAction(
action="break",
x=random.randint(0, obs.width - 1),
y=random.randint(0, obs.height - 1)
)
else:
action = WildfireAction(action="wait")
result = env.step(action)
obs = result.observation
episode_reward += result.reward or 0
episode_steps += 1
episode_rewards.append(episode_reward)
state = env.state
print(
f"Episode {episode + 1}: "
f"Reward={episode_reward:.2f}, "
f"Steps={episode_steps}, "
f"Burned={state.total_burned}, "
f"Extinguished={state.total_extinguished}"
)
print(f"\nAverage reward: {sum(episode_rewards) / len(episode_rewards):.2f}")
env.close()
๐ Web Interface#
The Wildfire Environment includes a custom web interface with visual grid display and wildfire-specific features.
Accessing the Web Interface#
Using Docker#
# Build base image (first time only)
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
# Build wildfire environment
docker build -t wildfire-env:latest -f envs/wildfire_env/server/Dockerfile .
# Run container
docker run -p 8000:8000 -e ENABLE_WEB_INTERFACE=true wildfire-env:latest
Then open: http://localhost:8000/web
Local Testing (No Docker)#
# Enable web interface with flag
ENABLE_WEB_INTERFACE=true PYTHONPATH=src uvicorn src.envs.wildfire_env.server.app:app --reload --host 0.0.0.0 --port 8000
Web Interface Features#
Left Pane: Action Interface#
Wildfire-specific action form
Action dropdown: Water (Extinguish Fire), Break (Create Firebreak), Wait (Do Nothing)
Coordinate inputs (X, Y) - auto-populated when clicking grid cells
Coordinates show/hide based on action type
Environment stats display
Step count
Water remaining
Breaks remaining
Burning cells count
Current state display
Status (Reset/Running)
Episode ID
Wind direction
Humidity
Control buttons
Reset Environment
Get State
Right Pane: Visual Grid & Logs#
Visual 2D Grid Display ๐ฅ
16ร16 grid rendered as color-coded cells
Color coding:
๐ฉ Green = Fuel (safe, value 1)
๐ฅ Orange/Red = Burning (fire, value 2)
โฌ Dark Gray = Ash (burned, value 0)
๐ซ Brown = Firebreak (value 3)
๐ฆ Blue = Watered/Damp (value 4)
Interactive: Click cells to set coordinates for water/break actions
Auto-updates: Grid refreshes automatically via WebSocket
Legend
Color-coded legend explaining all cell types
Action history
Log of all actions with timestamps
Shows action, observation, reward, and done status
Additional Features#
WebSocket connection - Real-time state updates without page refresh
Instructions panel - Collapsible environment documentation
Grid status indicator - Shows grid dimensions and cell count
Using the Web Interface#
Start the server (see above)
Open browser to:
http://localhost:8000/webClick โReset Environmentโ to initialize and display the grid
Interact with the grid:
Click on a cell to set coordinates for water/break actions
Or manually enter X, Y coordinates
Select action:
Choose
water,break, orwaitfrom the dropdown
Click โExecute Actionโ
Watch the grid update in real-time:
Fire spreads automatically
Cells change color based on state
Stats update automatically
Monitor resources in the stats panel (water, breaks, burning count)
๐ง Troubleshooting#
Common Issues#
1. Connection Errors#
Problem: ConnectionRefusedError or Cannot connect to server
Solutions:
Verify server is running:
curl http://localhost:8000/healthCheck Docker container:
docker ps | grep wildfireEnsure port 8000 is not in use:
lsof -i :8000
2. Index Errors#
Problem: IndexError: list index out of range
Solution: Ensure coordinates are within bounds:
# Always check bounds before accessing
if 0 <= x < obs.width and 0 <= y < obs.height:
action = WildfireAction(action="water", x=x, y=y)
3. Invalid Action Warnings#
Problem: Actions returning -0.05 reward repeatedly
Solutions:
Check
remaining_waterandremaining_breaksbefore using resourcesVerify coordinates are integers and within grid bounds
Use
action="wait"when resources are exhausted
4. Grid Format Confusion#
Problem: How to access grid cells?
Solution:
# Convert flat array to 2D
grid_2d = np.array(obs.grid).reshape(obs.height, obs.width)
# Access cell at (x, y)
cell_value = grid_2d[y][x]
# Or use flat index
index = y * obs.width + x
cell_value = obs.grid[index]
5. Docker Build Failures#
Problem: failed to solve: openenv-base:latest
Solution:
# Build base image first
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
# Then build wildfire image
docker build -t wildfire-env:latest -f envs/wildfire_env/server/Dockerfile .
Debugging Tips#
Enable verbose logging:
docker logs -f wildfire-env-container
Check environment state:
state = env.state print(f"State: {state}")
Validate actions:
obs = env.reset().observation print(f"Bounds: 0 <= x < {obs.width}, 0 <= y < {obs.height}") print(f"Resources: Water={obs.remaining_water}, Breaks={obs.remaining_breaks}")
Monitor grid changes:
prev_grid = obs.grid.copy() result = env.step(action) new_grid = result.observation.grid changes = [i for i, (a, b) in enumerate(zip(prev_grid, new_grid)) if a != b] print(f"Changed cells: {len(changes)}")
๐ Performance Considerations#
Grid Size Impact#
Small grids (16ร16): Fast, good for quick testing
Medium grids (32ร32): Default, balanced performance
Large grids (64ร64+): Slower, more realistic but requires more compute
Resource Limits#
Low water (4-8): Forces strategic decisions
High water (20+): More forgiving, easier to succeed
Low breaks (25): Emphasizes firebreak placement strategy
High breaks (100+): More freedom, less constraint
Episode Length#
Short episodes (50 steps): Fast iteration, good for debugging
Medium episodes (128 steps): Default, balanced
Long episodes (200+ steps): Better for complex strategies
๐งญ References#
Papers & Research#
Rothermel Model: USDA Forest Service - Surface Fire Spread Model
SimFire: MITRE Fireline Project
RL for Wildfires: arXiv:2311.15925
OpenEnv Framework#
Main Repository: OpenEnv GitHub
Documentation: See
rfcs/directory for design documentsOther Environments: See
src/envs/for more environment examples
๐ License#
This environment is part of the OpenEnv project. See the main LICENSE file for details.
๐ค Contributing#
Contributions welcome! Please see CONTRIBUTING.md in the main OpenEnv repository.
๐ Citations#
@techreport{rothermel2022surface,
title = {The Rothermel Surface Fire Spread Model and Associated Developments},
author = {Andrews, Patricia L. and Rothermel, Richard C.},
year = {2022},
institution = {USDA Forest Service},
number = {RMRS-GTR-371},
url = {https://www.fs.usda.gov/rm/pubs_series/rmrs/gtr/rmrs_gtr371.pdf}
}
@article{tapley2023reinforcement,
title = {Reinforcement Learning for Wildfire Mitigation in Simulated Disaster Environments},
author = {Tapley, A. and Dotter, M. and Doyle, M. and others},
journal = {arXiv preprint arXiv:2311.15925},
year = {2023},
url = {https://arxiv.org/abs/2311.15925}
}
@misc{mitrefireline2023simfire,
author = {{MITRE Fireline Project}},
title = {SimFire: Wildfire Simulator for Decision-Support and AI Research},
year = {2023},
howpublished = {\url{https://github.com/mitrefireline/simfire}}
}
@misc{wildfire-openenv-2025,
title = {Wildfire Environment for OpenEnv: Containment-Focused RL Simulation},
author = {OpenEnv Contributors},
year = {2025},
url = {https://github.com/openenv/openenv}
}
Happy firefighting! ๐ฅ๐