Skip to content
  • openenv
  • reinforcement-learning
  • wildfire
  • simulation

🌲 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.

Docker Python FastAPI License


📋 Table of Contents

  1. Why Wildfire Simulation?
  2. Quick Start
  3. Environment Overview
  4. Grid Format & Encoding
  5. Actions
  6. Observations
  7. Reward Structure
  8. Fire Spread Mechanics
  9. Configuration
  10. Installation & Usage
  11. API Reference
  12. Examples
  13. Web Interface
  14. Troubleshooting
  15. References

🔥 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

# 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
0 Ash (burned) Black ⚫ Burned out, cannot reignite
1 Fuel Green 🟩 Healthy vegetation, can ignite
2 Burning Red 🔥 Currently on fire, spreads to neighbors
3 Firebreak Brown 🟫 Barrier, fire cannot cross
4 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 == 0 - Using break when remaining_breaks == 0 - Missing 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:

  1. Burning cells persist for burn_lifetime = 3 ticks before turning to ash
  2. Each burning cell can ignite neighboring fuel cells (8 directions)
  3. Spread probability depends on:
  4. Base ignition probability: 0.30 (30% chance)
  5. Humidity factor: (1.0 - humidity) - higher humidity = less spread
  6. Wind multiplier:
    • +2.0x in wind direction
    • +0.5x against wind
    • +1.0x perpendicular
  7. Diagonal factor: 0.6x for diagonal neighbors (slower spread)

  8. Water/Damp cells (4) are immune to ignition while damp

  9. Firebreaks (3) cannot be crossed by fire
  10. 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
WILDFIRE_WIDTH Grid width in cells 32 8-128
WILDFIRE_HEIGHT Grid height in cells 32 8-128
WILDFIRE_HUMIDITY Initial humidity level 0.25 0.0-1.0
WILDFIRE_WIND Wind direction (fixed) Random N, NE, E, SE, S, SW, W, NW, CALM
WILDFIRE_SEED Random seed 3407 Any integer
WILDFIRE_MAX_STEPS Max steps per episode 128 10-1000
WILDFIRE_WATER_CAPACITY Initial water units 8 1-100
WILDFIRE_BREAK_CAPACITY Initial firebreak materials 50 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

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

  1. Start the server (see above)
  2. Open browser to: http://localhost:8000/web
  3. Click "Reset Environment" to initialize and display the grid
  4. Interact with the grid:
  5. Click on a cell to set coordinates for water/break actions
  6. Or manually enter X, Y coordinates
  7. Select action:
  8. Choose water, break, or wait from the dropdown
  9. Click "Execute Action"
  10. Watch the grid update in real-time:
  11. Fire spreads automatically
  12. Cells change color based on state
  13. Stats update automatically
  14. 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/health - Check Docker container: docker ps | grep wildfire - Ensure 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_water and remaining_breaks before using resources - Verify 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

  1. Enable verbose logging:

    docker logs -f wildfire-env-container
    

  2. Check environment state:

    state = env.state
    print(f"State: {state}")
    

  3. 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}")
    

  4. 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

OpenEnv Framework

  • Main Repository: OpenEnv GitHub
  • Documentation: See rfcs/ directory for design documents
  • Other 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! 🔥🚒