- openenv¶
Snake Environment¶
A multi-agent snake game environment for OpenEnv, based on marlenv's Snake-v1. This environment provides a single-agent interface to the classic snake game where the snake must navigate a grid, eat fruits, and avoid walls and its own body.
Overview¶
The Snake environment wraps the marlenv Snake-v1 environment to provide a clean OpenEnv-compatible interface. Multiple snakes can battle on a fixed size grid map, but this implementation focuses on single-agent gameplay.
Features¶
- Grid-based gameplay: Configurable grid size (default: 20x20)
- Fruit collection: Snake grows when eating fruits
- Partial observability: Optional vision range for limited field of view
- Customizable rewards: Configurable reward function for different game aspects
- Two control modes:
snake: Relative actions (turn left/right)human: Global directions (up/down/left/right)
Game Rules¶
- Snake dies when its head hits a wall or its own body
- Snake grows by one unit when it eats a fruit
- Episode ends when the snake dies or reaches maximum steps
- Rewards can be customized for: eating fruits, survival time, and death penalty
Quick Start¶
Using Docker (Recommended)¶
from envs.snake_env import SnakeAction, SnakeEnv
# Start environment from Docker image
client = SnakeEnv.from_docker_image("snake-env:latest")
# Reset to start new episode
result = client.reset()
print(f"Snake alive: {result.observation.alive}")
print(f"Grid shape: {len(result.observation.grid)}x{len(result.observation.grid[0])}")
# Take actions
result = client.step(SnakeAction(action=0)) # Continue straight
print(f"Reward: {result.reward}")
print(f"Score: {result.observation.episode_score}")
result = client.step(SnakeAction(action=1)) # Turn left
result = client.step(SnakeAction(action=2)) # Turn right
# Check game state
state = client.state()
print(f"Episode: {state.episode_id}")
print(f"Steps: {state.step_count}")
# Cleanup
client.close()
Using Local Server¶
# Install dependencies
cd src/envs/snake_env
pip install -e .
# Run server
uv run --project . server
Then connect from another terminal:
from envs.snake_env import SnakeAction, SnakeEnv
# Connect to running server
client = SnakeEnv(base_url="http://localhost:8000")
result = client.reset()
result = client.step(SnakeAction(action=0))
Actions¶
The action space depends on the observer mode:
Snake Mode (Default)¶
Relative actions based on current direction:
- 0: No-op (continue in same direction)
- 1: Turn left (90 degrees counterclockwise)
- 2: Turn right (90 degrees clockwise)
Human Mode¶
Global directional actions:
- 0: No-op
- 1: Move left
- 2: Move right
- 3: Move down
- 4: Move up
Observations¶
Each observation includes:
grid: The full game grid as a 2D array (height × width)observation: Encoded observation based on vision rangeepisode_score: Cumulative score in current episodeepisode_steps: Number of steps takenepisode_fruits: Number of fruits eatenepisode_kills: Number of kills (always 0 in single-agent mode)alive: Whether the snake is still alive
Configuration¶
Environment Parameters¶
from envs.snake_env.server.snake_environment import SnakeEnvironment
env = SnakeEnvironment(
height=20, # Grid height (default: 20)
width=20, # Grid width (default: 20)
snake_length=3, # Initial snake length (default: 3)
vision_range=5, # Partial observability (None for full grid)
observer='snake', # 'snake' or 'human' mode
max_episode_steps=1000, # Maximum steps per episode
reward_dict={ # Custom reward function
'fruit': 1.0, # Reward for eating fruit
'kill': 0.0, # Reward for kills (multi-agent)
'lose': -1.0, # Penalty for death
'win': 0.0, # Reward for winning (multi-agent)
'time': 0.0, # Reward per timestep
}
)
Custom Rewards¶
You can customize the reward function to encourage different behaviors:
# Encourage survival
reward_dict = {
'fruit': 1.0,
'lose': -10.0,
'time': 0.01, # Small reward for staying alive
}
# Fast fruit collection
reward_dict = {
'fruit': 10.0,
'lose': -1.0,
'time': -0.01, # Penalty for taking too long
}
Building and Deployment¶
Build Docker Image¶
From the repository root:
# Build base image first (if not already built)
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
# Build snake environment image
docker build -t snake-env:latest -f envs/snake_env/server/Dockerfile .
The Dockerfile uses pip install with requirements.txt for maximum compatibility.
Run Docker Container¶
# Run the container
docker run -p 8000:8000 snake-env:latest
# Or with environment variables
docker run -p 8000:8000 \
-e ENABLE_WEB_INTERFACE=true \
snake-env:latest
Web Interface¶
When ENABLE_WEB_INTERFACE=true is set, you can access the web interface at http://localhost:8000/web to interact with the environment through your browser.
Dependencies¶
The snake environment requires:
marlenv: Multi-agent snake game implementationgym==0.24.1: OpenAI Gym (required by marlenv)numpy: Numerical operations- Standard OpenEnv dependencies (fastapi, pydantic, uvicorn)
These are automatically installed when using Docker or installing via pip.
Example Training Loop¶
from envs.snake_env import SnakeAction, SnakeEnv
import random
# Connect to environment
env = SnakeEnv.from_docker_image("snake-env:latest")
# Training loop
for episode in range(10):
result = env.reset()
total_reward = 0
done = False
while not done:
# Simple random policy (replace with your agent)
action = SnakeAction(action=random.randint(0, 2))
result = env.step(action)
total_reward += result.reward
done = result.done
print(f"Episode {episode}: Reward={total_reward}, "
f"Fruits={result.observation.episode_fruits}, "
f"Steps={result.observation.episode_steps}")
env.close()
Troubleshooting¶
marlenv Installation Issues¶
If you encounter issues installing marlenv, you can install it from source:
pip install git+https://github.com/kc-ml2/marlenv.git
Import Errors¶
Make sure you're in the correct directory when running the server:
cd src/envs/snake_env
uv run --project . server
Docker Build Issues¶
Ensure the base image is built first:
docker build -t openenv-base:latest -f src/openenv/core/containers/images/Dockerfile .
Citation¶
The underlying snake game is from marlenv:
@MISC{marlenv2021,
author = {ML2},
title = {Marlenv, Multi-agent Reinforcement Learning Environment},
howpublished = {\url{http://github.com/kc-ml2/marlenv}},
year = {2021}
}
License¶
BSD 3-Clause License - See LICENSE file in the root directory.